08-08
23
自定义标签之 开发迭代的标签库
作者:Java伴侣 日期:2008-08-23
在没有迭代标签的时候,如果要循环输出内容到网页,我们往往这样做:
IterateTag.java
在doStartTag方法中,如果it不为null,那么就进行第一次迭代。在continueNext方法中如果it还有下一个,那么就继续迭代,如果没有下一个了,就返回SKIP_BODY,表示不再迭代。
除了上面的标签类外,还需要开发一个表示标签信息的类,如下
iterateTEI.java
<%
While(iterator.hasNext())
{
SomeObject obj = (SomeObject)iterator.Next();
out.println(obj.getComeValue());
}
%>
上面的while就是一个迭代,如果我们要开发出这样的标签,一般需要二个开发类,一具类实现BodyTagSupport接口,另一个类扩展TagExtraInfo类。TagExtraInfo旨在提供标签运行时的信息。下面来做个实例While(iterator.hasNext())
{
SomeObject obj = (SomeObject)iterator.Next();
out.println(obj.getComeValue());
}
%>
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中使用这些属性时必须提供对应的值。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;
}
}
}
在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
Contact .java
<%@ 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>
运行:<%@ 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>
评论: 0 | 引用: 0 | 查看次数: 585
发表评论