【Java.Web】JSP —— 标签库taglib —— 自定义JSP标签 —— JSP Tag API

JSP Tag API

Servlet 容器在运行翻译JSP文件时,如果遇到自定义标签,就会调用这个标签的处理类(Tag Handler Class)的相关方法。

标签处理类可以继承JSP Tag API中的TagSupport类或者BodyTagSupport类。

Package javax.servlet.jsp.tagext


该Package中主要类和接口如下:

【Java.Web】JSP —— 标签库taglib —— 自定义JSP标签 —— JSP Tag API_第1张图片



标签处理类的对象(Tag对象)有Servlet容器负责创建。Servlet容器在执行JSP文件时,如果遇到JSP文件中的自定义标签,就会寻找缓存中的相关Tag对象,如果还不存在,就创建一个Tag对象,把它放在缓存中,以便下次处理自定义标签时重复使用。

一个Tag对象在被创建后,就会一直存在可以被Servlet容器反复调用,当Web应用终止时,调用所有Tag对象的release()方法,然后销毁这些Tag对象。



JspTag接口

public interface JspTag

所有的标签处理类都要实现JspTag接口。这个接口只是一个标识接口,没有任何方法,主要是作为Tag和SimpleTag接口的共同接口。

  • 实现Tag接口的标签成为传统标签(Classis Tag)
  • 实现SimpleTag接口的标签成为简单标签(Simple Tag)


Tag接口

public interface Tag
extends JspTag

Tag接口定义了所有传统标签处理类都要实现的基本方法:

  • setPageContext(PageContext pc) —— 由Servlet容器调用该方法,向前标签处理对象(即Tag对象)传递当前的PageContext对象
  • setParent(Tag t) —— 由Servlet容器调用该方法,向当前Tag对象传递父标签的Tag对象
  • getParent() —— 返回Tag类型的父标签的Tag对象
  • release() —— 当Servlet容器需要释放Tag对象占用的资源时,会调用此方法
  • doStartTag() —— 当Servlet容器遇到标签的其实标志时,会调用此方法。其返回一个整数值,用来决定程序的后续流程。返回Tag.SKIP_BODY表示标签之间的主体内容被忽略,返回Tag.EVAL_BODY_INCLUDE表示标签之间的主体内容被正常执行
  • doEndTag() —— 当Servlet容器遇到标签的结束标志时,就会调用此方法。其也返回一个整数值,用来决定程序的后续流程。返回Tag.SKIP_PAGE表示立刻停止执行标签后面的JSP代码,网页上未处理的静态内容和Java程序片段均被忽略,任何已有的输出内容立刻返回到客户端的浏览器上;返回Tag.EVAL_PAGE表示按正常的流程继续执行JSP文件


当Servlet容器得到了Tag对象之后,按照下面的流程调用Tag对象的相关方法:

  • Servlet容器调用Tag对象的setPageContext()和setParent()方法,把当前JSP页面的PageContext对象及父标签处理对象传给当前的Tag对象。如果不存在,则把父标签处理对象设为null
  • Servlet容器调用Tag对象的一系列set方法,设置Tag对象的属性
  • Servlet容器调用Tag对象的doStartTag()方法
  • 如果doStartTag()方法返回Tag.SKIP_BODY,就不会执行标签主体的内容;如果返回Tag.EVAL_BODY_INCLUDE,就执行标签主体的内容
  • Servlet容器调用Tag对象的doEndTag()方法
  • 如果doEndTag()方法返回Tag.SKIP_PAGE,就不执行标签后续的JSP代码;如果返回Tag.EVAL_PAGE,就执行后续的JSP代码

【Java.Web】JSP —— 标签库taglib —— 自定义JSP标签 —— JSP Tag API_第2张图片



IterationTag接口

public interface IterationTag
extends Tag


IterationTag接口增加了重复执行标签主体内容的功能。

IterationTag接口定义了一个doAfterBody()方法,Servlet容器在执行完标签主体内容后,会调用此方法。如果Servlet容器未执行标签主体内容,那么就不会调用此方法。doAfterBody()方法也返回一个整数值,用来决定程序后续流程;返回Tag.SKIP_BODY表示不再执行标签主体的内容;返回IterationTag.EVAL_BODY_AGAIN表示重复执行标签主体的内容。

Servlet容器按照如下流程调用IterationTag对象的相关方法:

【Java.Web】JSP —— 标签库taglib —— 自定义JSP标签 —— JSP Tag API_第3张图片



BodyTag接口

public interface BodyTag
extends IterationTag


BodyTag接口增加了直接访问和操纵标签主体内容的功能。

BodyTag接口新增了两个方法:

  • setBodyContent(BodyContent bc) —— Servlet容器通过此方法向BodyTag对象传递一个用户缓存标签主体执行结果的BodyContent对象;
  • doInitBody() —— 当Servlet容器调用完setBodyContent()方法之后,在第一次执行标签主体之前,先调用此方法,该方法用于执行标签主体的初始化工作

当符合下面条件时,setBodyContent()和doInitBody()方法就不会被Servlet容器调用:

  • 标签主体为空
  • doStartTag()方法的返回值为Tag.SKIP_BODY或者Tag.EVAL_BODY_INCLUDE

只有同时符合一下两个条件,Servlet容器才会调用这个两个方法:

  • 标签主体不为空
  • doStartTag()方法的返回值为BodyTag.EVAL_BODY_BUFFERED


Servlet容器按照如下的流程调用BodyTag对象的相关方法:

【Java.Web】JSP —— 标签库taglib —— 自定义JSP标签 —— JSP Tag API_第4张图片




TagSupport类和BodyTagSupport类

public class TagSupport
extends Object
implements IterationTag, Serializable

public class BodyTagSupport
extends TagSupport
implements BodyTag


TagSupport类和BodyTagSupport类是标签实现类;用户自定义的标签处理类可以继承TagSupport类或者BodyTagSupport类。


TagSupport类的主要方法:

  • doStartTag() —— 当Servlet容器遇到自定义标签的起始标志时调用
  • doEndTag() —— 当Servlet容器遇到自定义标签的结束标志时调用
  • setValue(String key, Object value) —— 在标签处理对象中设置key/value
  • getValue(String key) —— 根据参数key返回匹配的value
  • removeValue(String key) —— 在标签出路对象中删除key/value
  • setPageContext(PageContext pc) —— 设置PageContext对象,该方法由Servlet容器在调用doStartTag()方法前调用
  • getParent() —— 返回父标签的处理对象


TagSupport类的成员变量:

  • parent —— 代表父标签的处理对象
  • pageContext —— 代表当前JSP页面的PageContext对象
  • Servlet容器在调用doStartTag()之前,会先调用setPageContext()和setParent()方法,设置pageContext和parent成员变量;其余的方法可直接使用;
  • 在TagSupport的构造方法中不能访问pageContext对象,因为此时Servlet容器还没有对pageContext成员进行初始化


主要重新实现的TagSupport类的方法:

对于用户自定义的标签处理类,主要重新实现TagSupport类中的以下方法,

  • doStartTag() —— 
  • doEndTag() ——
  • 如果希望Servlet容器重复执行标签主体的内容,那么还可以重新实现TagSupport类的doAfterBody()方法


用户自定义的标签属性:

如果在标签中包含自定义的属性,那么在标签处理类中应该将这个属性作为成员变量,并且分别提供设置读取属性的方法,

例如:

<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对象中。










你可能感兴趣的:(java,Web)