在自定义标签之HelloWorld中用Tag和TagSupport实现了简单的HelloWorld,那么这篇记录带Body的标签开发,带有Body的Tag必须要实现javax.servlet.jsp.tagext.BodyTag接口,BodyTag接口中定义了一些处理标签体的方法 。
通过实现BodyTag接口,就可以方便地操作标签体,比如可以让标签体迭代多次等。BodyTag的处理过程如下:前4步与一般的标签体一样
1:当容器创建一个新的标签实例后,通过setPageContext设置标签的页面上下文。
2:使用setParent方法设置这个标签的上一级标签。如果没有上一级嵌套,设置为空。
3:设置标签的属性。这个属性在标签库描述文件中定义。如果没有定义属性就不调用此类方法。
4:调用 doStartTag方法,这个方法可以返回EVAL_BODY_INCLUDE和SKIP_BODY。当返回EVAL_BODY_INCLUDE时,就计算标签的BODY,如果返回SKIP_BODY,就不计算标签的BODY。
5:调用setBodyContent设置当前的BodyContent
6:调用doInitBody。如果在计算BodyContent时需要进行一些初始化,就在这个方法中进行。
7:每次计算完BodyTag后调用 doAfterBody。如果返回EVAL_BODY_TAG,表示继续计算一次BodyTag,直到返回SKIP_BODY才继续执行第 8 步。
8:调用doEndTag方法,这个方法可以返回EVAL_PAGE或者SKIP_PAGE。当返回 EVAL_PAGE时,容器在标签结束时继续计算JSP页面的其他部份,如果返回SKIP_PAGE,容器将在标签结果时停止计算JSP页面的其他部分。
9:调用release()方法释放标签程序占用的任何资源
好了,废话我也不希望多说,下面来一个实例:
A:标签的实现代码
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.Hashtable;
import java.io.Writer;
import java.io.IOException;
public class BodyTagExample extends BodyTagSupport
{
int counts;//counts为迭代的次数。
public BodyTagExample()
{
super();
}
/**
*设置counts属性。这个方法由容器自动调用。
*/
public void setCounts(int c)
{
this.counts=c;
}
/**
*覆盖doStartTag方法
*/
public int doStartTag() throws JspTagException
{
System.out.println("doStartTag");
if(counts>0)
{
return EVAL_BODY_TAG;
}
else
{
return SKIP_BODY;
}
}
/**
*覆盖doAfterBody方法
*/
public int doAfterBody() throws JspTagException
{
System.out.println("doAfterBody"+counts);
if(counts>1)
{
counts--;
return EVAL_BODY_TAG;
}
else
{
return SKIP_BODY;
}
}
/**
*覆盖doEndTag方法
*/
public int doEndTag() throws JspTagException
{
System.out.println("doEndTag");
try
{
if(bodyContent != null)
{
bodyContent.writeOut(bodyContent.getEnclosingWriter());
}
}
catch(java.io.IOException e)
{
throw new JspTagException("IO Error: " + e.getMessage());
}
return EVAL_PAGE;
}
public void doInitBody() throws JspTagException{
System.out.println("doInitBody");
}
public void setBodyContent(BodyContent bodyContent)
{
System.out.println("setBodyContent");
this.bodyContent=bodyContent;
}
}
每次计算 完Body时,都会调用 doAfterBody方法。
B:标签描述文件mytag.tld中加入
<name>loop</name>
<tag-class>eflylab.BodyTagExample</tag-class>
<body-content>jsp</body-content><!-- 必须为jsp -->
<attribute>
<name>counts</name><!-- 这个是我们资源源文件中的属性,同时源文件中必须要有setCounts(int counts)方法 -->
<required>true</required><!-- 必需要给定 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<html>
<head>
<title>body tag</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<HR>
<bodytag:loop counts="5">
现在的时间是: <%=new java.util.Date()%><BR>
</bodytag:loop>
<HR>
</BODY>
</HTML>
同时控制台:
这里打印的内容就是调用标签中方法的顺序。可以看出除了doAfterBody外,其他方法都只调用了一次。doAfterBody在每次循环完后都会调用。