在没有迭代标签的时候,如果要循环输出内容到网页,我们往往这样做:
<%
While(iterator.hasNext())
{
SomeObject obj = (SomeObject)iterator.Next();
out.println(obj.getComeValue());
}
%>
While(iterator.hasNext())
{
SomeObject obj = (SomeObject)iterator.Next();
out.println(obj.getComeValue());
}
%>
上面的while就是一个迭代,如果我们要开发出这样的标签,一般需要二个开发类,一具类实现BodyTagSupport接口,另一个类扩展TagExtraInfo类。TagExtraInfo旨在提供标签运行时的信息。下面来做个实例
IterateTag.java
package eflylab;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.*;
public class IterateTag extends BodyTagSupport
{
/** *//**
*Tag的属性
*/
private String name;
//it为要迭代的对象
private Iterator it;
//type表示it中对象的类型
private String type;
/** *//**
*设置属性collection
*/
public void setCollection(Collection collection)
{
if(collection.size()>0)
it=collection.iterator();
}
public void setName(String name)
{
this.name=name;
}
public void setType(String type)
{
this.type=type;
}
/** *//**
*如果it属性为null,那么忽略计算tagbody。
*/
public int doStartTag()throws JspTagException
{
if(it==null)
return SKIP_BODY;
else
return continueNext(it);
}
public int doAfterBody()throws JspTagException
{
return continueNext(it);
}
public int doEndTag()throws JspTagException
{
try
{
if(bodyContent!=null)
bodyContent.writeOut(bodyContent.getEnclosingWriter());
}
catch(java.io.IOException e)
{
}
return EVAL_PAGE;
}
/** *//**
*保护方法,用于把it.next()设置为pagecontext的属性
*/
protected int continueNext(Iterator it)throws JspTagException
{
if(it.hasNext())
{
pageContext.setAttribute(name,it.next(),PageContext.PAGE_SCOPE);
return EVAL_BODY_TAG;
}
else
{
return SKIP_BODY;
}
}
}
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.*;
public class IterateTag extends BodyTagSupport
{
/** *//**
*Tag的属性
*/
private String name;
//it为要迭代的对象
private Iterator it;
//type表示it中对象的类型
private String type;
/** *//**
*设置属性collection
*/
public void setCollection(Collection collection)
{
if(collection.size()>0)
it=collection.iterator();
}
public void setName(String name)
{
this.name=name;
}
public void setType(String type)
{
this.type=type;
}
/** *//**
*如果it属性为null,那么忽略计算tagbody。
*/
public int doStartTag()throws JspTagException
{
if(it==null)
return SKIP_BODY;
else
return continueNext(it);
}
public int doAfterBody()throws JspTagException
{
return continueNext(it);
}
public int doEndTag()throws JspTagException
{
try
{
if(bodyContent!=null)
bodyContent.writeOut(bodyContent.getEnclosingWriter());
}
catch(java.io.IOException e)
{
}
return EVAL_PAGE;
}
/** *//**
*保护方法,用于把it.next()设置为pagecontext的属性
*/
protected int continueNext(Iterator it)throws JspTagException
{
if(it.hasNext())
{
pageContext.setAttribute(name,it.next(),PageContext.PAGE_SCOPE);
return EVAL_BODY_TAG;
}
else
{
return SKIP_BODY;
}
}
}
由于BodyTagSupport类实现了IteratorTag接口,所以在开发迭代标签时,可以直接从BodyTagSupport类继承,IterateTag就是从BodyTagSupport类继承的例子。在IterateTag中,有3个属性,它们是name,type和it。name代表了在pageContext中标识的一个属性的名字;type代表了待迭代的内容的类型;it代表了要迭代的内容。在IterateTag中必须提供这些属性的setter方法,并且在JSP中使用这些属性时必须提供对应的值。
在doStartTag方法中,如果it不为null,那么就进行第一次迭代。在continueNext方法中如果it还有下一个,那么就继续迭代,如果没有下一个了,就返回SKIP_BODY,表示不再迭代。
除了上面的标签类外,还需要开发一个表示标签信息的类,如下
iterateTEI.java
package eflylab;
import javax.servlet.jsp.tagext.*;
//TagExtraInfo用于提供一些在标签翻译时相关的信息。
public class IterateTEI extends TagExtraInfo
{
public IterateTEI()
{
super();
}
public VariableInfo[] getVariableInfo(TagData data)
{
return new VariableInfo[]
{
new VariableInfo(
data.getAttributeString("name"),
data.getAttributeString("type"),
true,
VariableInfo.NESTED
),
};
}
}
import javax.servlet.jsp.tagext.*;
//TagExtraInfo用于提供一些在标签翻译时相关的信息。
public class IterateTEI extends TagExtraInfo
{
public IterateTEI()
{
super();
}
public VariableInfo[] getVariableInfo(TagData data)
{
return new VariableInfo[]
{
new VariableInfo(
data.getAttributeString("name"),
data.getAttributeString("type"),
true,
VariableInfo.NESTED
),
};
}
}
需要说明的是VariableInfo的几个参数,如下:
NESTED 标签中的参数在starttag到endtag之间是有效的。
AT_BEGIN 标签中的参数在标签的开始到JSP结束是有效的。
AT_END 标签中的参数在标签的结束到JSP页面的结束是有效的。
当然另外在标签的描述文件TLD中要加上这二类的描述
<tag>
<name>iterate</name>
<tag-class>eflylab.IterateTag</tag-class>
<tei-class>eflylab.IterateTEI</tei-class>
<body-content>jsp</body-content>
<attribute>
<name>collection</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>name</name>
<required>true</required>
</attribute>
<attribute>
<name>type</name>
<required>true</required>
</attribute>
</tag>
<name>iterate</name>
<tag-class>eflylab.IterateTag</tag-class>
<tei-class>eflylab.IterateTEI</tei-class>
<body-content>jsp</body-content>
<attribute>
<name>collection</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>name</name>
<required>true</required>
</attribute>
<attribute>
<name>type</name>
<required>true</required>
</attribute>
</tag>
测试代码:
Company .java
package eflylab;
import java.util.*;
import java.io.*;
public class Company implements Serializable {
private String name=null;
private Collection contacts=new HashSet();
private Contact lnkContact;
public Company(){}
public String getName()
{
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection getContacts()
{
return contacts;
}
public void addContact(Contact contact)
{
contacts.add(contact);
}
}
package eflylab;
import java.util.*;
import java.io.*;
public class Company implements Serializable {
private String name=null;
private Collection contacts=new HashSet();
private Contact lnkContact;
public Company(){}
public String getName()
{
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection getContacts()
{
return contacts;
}
public void addContact(Contact contact)
{
contacts.add(contact);
}
}
Contact .java
package eflylab;
import java.util.*;
import java.io.*;
public class Contact implements Serializable {
private String name=null;
private String phone=null;
private String email=null;
private String comment=null;
public Contact(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
package eflylab;
import java.util.*;
import java.io.*;
public class Contact implements Serializable {
private String name=null;
private String phone=null;
private String email=null;
private String comment=null;
public Contact(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}