编写标签对应的实现类时,需要重载BodyTagSupport类几个方法:doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag(),他们执行顺序如下:doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,如果返回EVAL_BODY_ INCLUDE则继续执行;如果返回SKIP_BODY则接下来的doInitBody(),setBodyContent(), doAfterBody()三个方法不会被执行,而直接执行doEndTag()方法。
setBodyContent()方法用于设置标签体内容,如果在此之前要作一些初始化工作,则在doInitBody()方法中完成。标签体内容执行完后,会调用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY,
EVAL_PAGE或SKIP_PAGE。如果返回EVAL_BODY_TAG则会再次设置标签体内容,直到返回SKIP_BODY;如果返回EVAL_PAGE则标签体执行完后会继续执行JSP页面中接下来的部分;如果返回SKIP_PAGE,则JSP页面的后续内容将不再执行。
【实例110】 开发带标签体的标签:bodyTag1
本实例将要开发一个带标签体的标签bodyTag1,这个标签有一个属性countNum,用于设置输出标签体内容的次数,输出内容为当前的系统时间。
(1)第一步:开发标签实现类。
BodyTag1.java
package body;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class bodyTag1 extends BodyTagSupport{
private int countNum=0;//循环显示时间的次数
private int currentNum=1;//当前执行次数
//----标签开始时调用此方法-------
public int doStartTag(){
try{
JspWriter out=pageContext.getOut();
out.print("标签开始了:<br>");
if(countNum>0)
return EVAL_BODY_TAG;
else
return SKIP_BODY;
}catch(Exception e){
System.out.println(e);
return SKIP_BODY;
}
}
//----标签体执行完后调用此方法----
public int doAfterBody(){
try{
JspWriter out=pageContext.getOut();
out.print("第"+currentNum+"次执行标签体。标签体执行完毕。<br>");
if(countNum>1){//如果还需要执行标签体
countNum--;
currentNum++;
return EVAL_BODY_TAG;
}else return SKIP_BODY;
}catch(Exception e){
System.out.println(e);
return SKIP_BODY;
}
}
//----标签结束时调用此方法-------
public int doEndTag(){
try{
JspWriter out=pageContext.getOut();
//----输出标签体的内容----
bodyContent.writeOut(bodyContent.getEnclosingWriter());
out.print("标签结束了。");
}catch(Exception e){
System.out.println(e);
}
return EVAL_PAGE;
}
public int getCountNum() {
return countNum;
}
public void setCountNum(int countNum) {
this.countNum = countNum;
this.currentNum=1;
}
}
执行标签体并不会直接输出标签体中的内容,因此本实例在doEndTag()方法中一次性把执行的结果输出。
(2)第二步:编写标签描述tld文件。
因为本章所有实例共用一个Web应用,故本例在myTag.tld文件中增加内容。在<taglib>与</taglib>之间增加的内容如下:
<!-- bodyTag1-->
<tag>
<!-- 标签名称-->
<name>bodyTag1</name>
<!-- 标签对应的处理类-->
<tag-class>body.bodyTag1</tag-class>
<!-- 标签体内容,有标签体则设为jsp-->
<body-content>jsp</body-content>
<!-- 标签的属性声明-->
<attribute>
<name>countNum</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
对于属性countNum的声明中,<required>设置为true,表示此属性为必输项;<rtexprvalue>设置为true,表示标签体支持运行时的表达式取值,如果为false则表示标签体为一个静态文本,默认情况下设置为true。
(3)第三步:在Web应用的web.xml文件中声明标签库引用。
同样,本例与实例108使用同一个tld文件,不必再修改。
(4)第四步:在JSP页面中声明并调用标签。
UseBodyTag1.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.Date" %>
<html>
<head>
<title>开发带有标签体的标签</title>
</head>
<body>
下面是应用这个带有属性的自定义标签的结果:<br>
<myTag:bodyTag1 countNum="6">
现在的时间是:<%=new Date()%><br>
</myTag:bodyTag1>
</body>
</html>