在没有迭代标签的时候,如果要循环输出内容到网页,我们往往这样做:

<%
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;
}
}
}
由于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
),
};
}
}
需要说明的是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>
测试代码:

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);
}
}

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;
}


public void setEmail(String email)
{
this.email = email;
}


public String getComment()
{
return comment;
}

public void setComment(String comment)
{
this.comment = comment;
}
}




<%
@ page pageEncoding="GBK" %>

<%
@ taglib uri="/demotag" prefix="mt"%>

<%
eflylab.Company comp=new eflylab.Company();
comp.setName("huayuan");
eflylab.Contact contact1=new eflylab.Contact();
contact1.setName("bar ,foo");
contact1.setEmail("dd@tsinghua.eud.cn");
contact1.setPhone("2975349875");
contact1.setComment("java programe");
eflylab.Contact contact2=new eflylab.Contact();
contact2.setName("bar ,foo");
contact2.setEmail("dd@tsinghua.eud.cn");
contact2.setPhone("2975349875");
contact2.setComment("java programe");
eflylab.Contact contact3=new eflylab.Contact();
contact3.setName("bar ,foodf");
contact3.setEmail("dd@tsinghua.euddfdf.cn");
contact3.setPhone("2975349875dd");
contact3.setComment("java progrdfame");
comp.addContact(contact1);
comp.addContact(contact2);
comp.addContact(contact3);
request.setAttribute("company",comp);
%>
<html>
<head>
<title>迭代标签演示</title>
</head>
<body>
<jsp:useBean id="company" scope="request" type="eflylab.Company"/>

<font size=+2>我的一些和<b>
<jsp:getProperty name="company" property="name"/>
公司联系</b>
</font>
<hr>
<table border=1>
<tr>
<td>姓名</td>
<td>电话</td>
<td>email</td>
<td>备注</td>
</tr>
<mt:iterate name="contact" collection="<%=company.getContacts()%>" type="eflylab.Contact">
<tr>
<td>
<jsp:getProperty name="contact" property="name"/>
</td>
<td>
<jsp:getProperty name="contact" property="phone"/>
</td>
<td>
<jsp:getProperty name="contact" property="email"/>
<td>
<jsp:getProperty name="contact" property="comment"/>
</td>
</tr>
</mt:iterate>
</table>
<hr>
</body>
</html>
运行: