JspTag Tag IterationTag BodyTag SimpleTag 接口
SimpleTagSupport和TagSupport和BodyTagSupport都是实现相应接口的类
编写一个定制动作,往往都是继承其中的类。通过继承SimpleTagSupport的定制动作为简单标记处理器,继承TagSupport或BodyTagSupport的定制标签为传统标记处理器,原因是传统标记处理器是Jsp1.1 1.2版本的时候使用的,而简单标记处理器是Jsp2.0才提供的,顾名思义简单标记处理器相对传统标记处理器实现的更为简单。
JspTag(Interface)
JspTag接口并没有任何方法,只是作为SimipleTag和Tag接口的一个公共基类,以允许由传统标记处理器和简单标记处理器所实现的定制动作能够嵌套。
Tag(Interface)
Tag接口是一个传统标记处理器的接口,不能够不能够操作他的体,Tag接口定义了最基本的传统标记处理器和Jsp页面实现类之间的通信协议。它定义了标记的生命周期,并且提供了一些调用方法在标记的开始和结束时。
Tag接口提供了pageContext对象和父标记的setter和getter方法。
Jsp页面实现类在调用doStartTag()和doEndTag()方法前,调用setPageContext()方法和setParent()方法来设置页面上下文属性和父标记属性。
Tag接口有两个主要动作doStartTag()和doEndTag()。当所有的属性被初始化后,doStartTag和doEndTag方法就会被标记处理器调用。当doEndTag方法调用完后,标记处理器依然有效,可以处理更多的调用请求。(并且会保留自己的属性)
当第一次调用该标记时,所有的属性都为默认值,然后标记处理器会调用setPageContext(),setParent()和各种属性值的setter()方法。当所有属性都初始化完成后,就会调用doStartTag()方法,doStartTag()方法可以返回SKIP_BODY或_BODY_INCLUDE,当返回SKIP_BODY时,处理器会跳过体元素直接执行doEndTag()。当返回_BODY_INCLUDE时,标记处理器会处理题中元素并将计算结果加入到当前输出流中。如果在标记库描述符文件中指定<body-content>为empty时,doStartTag()方法必须返回SKIP_BODY.
Tag接口中字段:
static int _BODY_INCLUDE
表示计算体中元素并加入到输出流中
static int _PAGE
表示继续执行页面
static int SKIP_BODY
表示忽略计算元素体
static int SKIP_PAGE
表示忽略页面的执行
Tag接口中的方法:
int doStartTag()
该方法执行时会假定所有的属性都已初始化完成,但是体元素尚未执行,该方法返回Tag._BODY_INCLUDE或BodyTag._BODY_BUFFERED来指示体元素将被计算或者返回Tag.SKIP_BODY来指示忽略体元素.BodyTag._BODY_BUFFERED只有在标记处理器实现BodyTag时才有效.JSP容器将使AT_BEGIN和NESTED范围内的变量同步,在doStartTag()结束时,除非标记处理器实现了BodyTag接口,并且doStartTag()方法返回的是BodyTag._BODY_BUFFERED.
int doEndTag()
该方法返回_PAGE时,会执行剩余的页面,如果返回SKIP_PAGE剩余页面将不会执行.请求将会结束. JSP容器将使AT_BEGIN和AT_END变量值同步,在结束doEndTag方法调用后.
Tag getParent()
得到父标签的实例(最靠近的标记处理器)
void release()
标记处理器将调用它来释放状态
void setPageContext(PageContext pc)
标记处理器将调用它来设置页面上下文
void setParent(Tag t)
标记处理器将调用它来设置父标记
IterationTag(Interface)
IterationTag接口是继承自Tag接口,并且增加了一个方法来多次执行它的体元素.
它新增了一个doAfterBody()方法,该方法可以通过返回值来确定是否需要再执行一遍体.如果返回IterationTag._BODY_AGAIN则体将会被重新计算.如果返回Tag.SKIP_BODY则将跳过体,继续执行doEndTag.
如果标记库描述符文件指定<body-content>为empty,则doStartTag()方法必须返回SKIP_BODY.
至于执行完doStartTag()方法后该执行哪个函数,取决于doStartTag()的返回值和体是否为空,不能根据TLD中的声明.如果SKIP_BODY被返回,则不计算体而直接调用doEndTag()函数.如果_BODY_INCLUDE被返回并且体不为空,则体将会并计算并送入输出流中.然后doAfterBody()被调用,在0次到多次循环后,doEndTag()方法被调用.
IterationTag中的字段:
static int _BODY_AGAIN
在doAfterBody()中返回该值,会再次计算体.
TagSupport类为IterationTag接口的实现类,在TagSupport中新增的字段:
protected java.lang.String id;
protected PageContext
private Tag parent;
private Hashtable<Object> values;
IterationTag中的方法:
int doAfterBody()
这个方法由JSP实现类在每次计算完体后调用,如果没有体元素,该方法不会被执行.
JSP容器将使AT_BEGIN和NESTED变量再同步,在调用doAfterBody之后.
TagSupport类新增的方法:
Staitc findAncestorWithClass(Tag from,Class klass)
该方法返回一个与指定实例有密切关系的指定类型的对象引用.
String getId()
Enumeration<String> getValues()
void release()
BodyTag(Interface)
该接口是继承自IterationTag接口,增加了一个可以处理体中内容的方法.
标记处理器可以取得体中的内容,通过bodyContext.getString方法.将它转换成一个String.或者标记处理器可以使用bodyContent.writeOut方法将体的内容写入到包装JspWriter中
如果在doStartTag方法中返回_BODY_BUFFERED,则一个BodyContent的实例将会创建(由JSP编译器完成)来捕获体的计算结果.JSP编译器通过调用pageContext.pushBody()方法来获得BodyContent对象.JSP编译器通过调用pageContext.popBody()方法来返回BodyContent对象,同时会重新储存输出流中的内容.
BodyTag新增了一个bodyContent属性,是一个BodyContent的实例,JSP页面实现类将把体的计算结果放在bodyContent中.如果doStartTag()函数返回_BODY_BUFFERED时并且相应体不为空的话,setBodyContent方法才会被调用.
除了setBodyContent方法外,还有一个新的方法:doInitBody()方法,他将在setBodyContent方法执行之后在体被计算之前被调用.这个方法仅仅在doStartTag()方法返回_BODY_BUFFERED时被调用.
如果标记描述符文件指定<body-content>为empty,则doStartTag()方法必须返回SKIP_BODY,否则doStartTag()方法可以返回SKIP_BODY,_BODY_INCLUDE,或_BODY_BUFFERED.
注意,在调用doStartTag()方法后会调用什么方法,取决于返回值和是否体为空,而不是TLD中的声明.
如果doStartTag()方法返回的是SKIP_BODY则不会再计算体,直接执行doEndTag方法.
如果doStartTag()方法返回的是_BODY_INCLUDE并且体不为空,setBodyContent和doInitBody方法不会被调用,体仅仅是被计算并送入输出流中.然后doAfterBody方法被调用.如果体为空,只有doStartTag和doEndTag被调用
如果doStartTag()方法返回的是_BODY_BUFFERED并且体不为空,setBodyContent,doInitBody将会被调用,然后体会被计算,然后doAfterBody会被调用.
BodyTag中的字段
static int _BODY_BUFFERED
static int _BODY_TAG (过时的)
BodyTag中的方法
void setBodyContent(BodyContent b)
void doInitBody()throws JspException
JSP容器会使任何AT_BEGIN和NESTED的变量再同步,在调用doInitBody()方法后.
BodyTagSupport类是BodyTag接口的实现类,BodyTagSupport中新增的方法:
BodyContent getBodyContent()
JspWriter getPreviousOut()
void release()
SimpleTag(Interface)
简易标记处理器不同于传统标记处理器,简易标记处理器中只提供了一个简单的doTag方法,该方法仅仅被调用一次,所有逻辑处理,迭代,体计算等都可以在这个方法中完成.
为了提供bodyContent,SimpleTag提供了setJspBody()方法,容器调用setJspBody方法使用一个JspFragment对象,封装了标记的体.标记处理器可以调用JspFragment对象的invoke方法来计算体,并且可以多次计算.
简易标记处理器必须有一个公共的无参数的构造函数,大部分的简易标记处理应该继承SimpleTagSupport类.
注意:
1. 一个新的标记处理器会在容器调用它的无参构造函数时创建,不像传统标记处理器,简易标记处理器不会存储和再生.
2. 容器会负责调用setJspContent和setParent方法.setParent方法仅仅会在该标记嵌套在另一个标记中时才会调用.
3. 容器会负责调用各种属性的setter方法.
4. 如果体存在,setJspBody方法将会被容器调用来设置体,作为一个JspFragment对象.如果体为空,这个方法是不会调用的.
5. doTag方法也是由容器负责调用,在函数内可以完成各种业务逻辑功能.
6. doTag方法返回中的所有变量都是同步的.
SimpleTag中的方法:
void doTag()
如果一个页面要终止执行,可以让标记处理器throw SkipPageException
JspTag getParent()
void setJspBody(JspFragment jspBody)
void setJspContext(JspContext pc)
void setParent(JspTag parent)
在SimpleTagSupport类中增加的方法:
static JspTag findAncestorWithClass(JspTag from,java.langClass<?> klass)
该方法返回一个与指定实例有密切关系的指定类型的对象引用.
JspTag getParent()
该方法返回该标记的父标记引用