Servlet 容器在运行翻译JSP文件时,如果遇到自定义标签,就会调用这个标签的处理类(Tag Handler Class)的相关方法。
标签处理类可以继承JSP Tag API中的TagSupport类或者BodyTagSupport类。
Package javax.servlet.jsp.tagext
该Package中主要类和接口如下:
标签处理类的对象(Tag对象)有Servlet容器负责创建。Servlet容器在执行JSP文件时,如果遇到JSP文件中的自定义标签,就会寻找缓存中的相关Tag对象,如果还不存在,就创建一个Tag对象,把它放在缓存中,以便下次处理自定义标签时重复使用。
一个Tag对象在被创建后,就会一直存在可以被Servlet容器反复调用,当Web应用终止时,调用所有Tag对象的release()方法,然后销毁这些Tag对象。
public interface JspTag
所有的标签处理类都要实现JspTag接口。这个接口只是一个标识接口,没有任何方法,主要是作为Tag和SimpleTag接口的共同接口。
public interface Tag extends JspTag
Tag接口定义了所有传统标签处理类都要实现的基本方法:
当Servlet容器得到了Tag对象之后,按照下面的流程调用Tag对象的相关方法:
public interface IterationTag extends Tag
IterationTag接口增加了重复执行标签主体内容的功能。
IterationTag接口定义了一个doAfterBody()方法,Servlet容器在执行完标签主体内容后,会调用此方法。如果Servlet容器未执行标签主体内容,那么就不会调用此方法。doAfterBody()方法也返回一个整数值,用来决定程序后续流程;返回Tag.SKIP_BODY表示不再执行标签主体的内容;返回IterationTag.EVAL_BODY_AGAIN表示重复执行标签主体的内容。
Servlet容器按照如下流程调用IterationTag对象的相关方法:
public interface BodyTag extends IterationTag
BodyTag接口增加了直接访问和操纵标签主体内容的功能。
BodyTag接口新增了两个方法:
当符合下面条件时,setBodyContent()和doInitBody()方法就不会被Servlet容器调用:
只有同时符合一下两个条件,Servlet容器才会调用这个两个方法:
Servlet容器按照如下的流程调用BodyTag对象的相关方法:
public class TagSupport extends Object implements IterationTag, Serializable public class BodyTagSupport extends TagSupport implements BodyTag
TagSupport类和BodyTagSupport类是标签实现类;用户自定义的标签处理类可以继承TagSupport类或者BodyTagSupport类。
对于用户自定义的标签处理类,主要重新实现TagSupport类中的以下方法,
如果在标签中包含自定义的属性,那么在标签处理类中应该将这个属性作为成员变量,并且分别提供设置读取属性的方法,
例如:
<prefix:mytag username="New User"> ... ... </prefix:mytag> private String username; public void setUsername(String username){ this.username = username; } public String getUsername(){ return usrname; }
如果希望操纵标签主体内容,可以让自定义的标签处理类继承BodyTagSupport类。
BodyTagSupport类有一个重要的bodyContent成员变量,用于缓存标签主体的执行结果。
如果标签处理类doStartTag()方法返回BodyTag.EVAL_BODY_BUFFERED,那么Servlet容器在执行标签主体之前,会先创建一个用来缓存标签主体执行结果的BodyContent对象,接着调用setBodyContent()方法,使得成员变量bodyContent引用BodyContent对象;然后再调用doInitBody()方法。Servlet容器在执行标签主体内容时,会把得到的执行结果缓存到BodyContent对象中。