JSTL自定义标签

本文自定义输出helloworld标签和自定义list循环遍历标签
自定义标签的基本步骤如下:
(1)把标签处理类及相关类的class文件存放在WEB-INF/classes目录下。
(2)把TLD标签库描述文件存放在WEB-INF目录或者其自定义的子目录下。
(3)在web.xml文件中声明所引用的标签库。
(4)在JSP文件中使用标签库中的标签。




自定义实现Tag接口的标签步骤
一、创建处理标签的java类,标签处理类要实现javax.servlet.jsp.tagext.Tag接口
输出helloworld标签的形式<h:hello></h:hello>
(1)Tag接口中的方法简介
1.public void setPageContext(PageContext pc)由Servlet容器调用传递给处理类pageContext对象
2.public void setParent(Tag t)由Servlet容器调用传递给标签处理类该标签的父标签
3.public Tag getParent()返回该标签的父标签
4.doStartTag()当Servlet容器遇到该标签的启始标记的时候会调用该方法。
doStartTag()方法返回一个整数值,用来决定程序的后续流程。
它有两个可选值,即Tag.SKIP_BODY和Tag.EVAL_BODY_INCLUDE。
Tag.SKIP_BODY表示标签之间的主体内容被忽略,
Tag.EVAL_BODY_INCLUDE表示标签之间的主体内容被正常执行。
5.doEndTag()当Servlet容器遇到标签的结束标志时,就会调用doEndTag()方法。
doEndTag()方法也返回一个整数值,用来决定程序后续流程。
它有两个可选值,即Tag.SKIP_PAGE和Tag.EVAL_PAGE。
Tag.SKIP_PAGE表示立刻停止执行标签后面的JSP代码,网页上未处理的静态内容和Java程序片段均被忽略,任何已有的输出内容立刻返回到客户的浏览器上。
Tag.EVAL_PAGE表示按正常的流程继续执行JSP文件。
6.public void release()当Servlet容器需要释放Tag对象占用的资源时,会调用此方法。

(2)Servlet容器调用Tag对象的相关方法的流程
1.Servlet容器调用Tag对象的setPageContext()和setParent()方法,把当前JSP页面的PageContext对象及父标签处理对象传给当前Tag对象。如果不存在父标签,则把父标签处理对象设为null。
2.Servlet容器调用Tag对象的一系列set方法,设置Tag对象的属性。如果标签没有属性,则无需这个步骤。
3.Servlet容器调用Tag对象的doStartTag()方法。
4.如果doStartTag()方法返回Tag.SKIP_BODY,就不执行标签主体的内容;如果doStartTag()方法返回Tag.EVAL_BODY_INCLUDE,就执行标签主体的内容。
5.Servlet容器调用Tag对象的doEndTag()方法。
6.如果doEndTag()方法返回Tag.SKIP_PAGE,就不执行标签后续的JSP代码;如果doEndTag()方法返回Tag.EVAL_PAGE,就执行标签后续的JSP代码。
注意:一个Tag对象在被创建后,就会一直存在,可以被Servlet容器重复调用。当Web应用终止时,Serlvet容器会先调用该Web应用中的所有Tag对象的release()方法,然后销毁这些Tag对象。

(3)HelloWorld标签处理类cn.pdsu.HelloTaglib


(4)HelloWorld标签描述TLD文件如下:


 
  (5)在web.xml中注册标签描述tld文件
  添加如下内容:
 



  (6)在jsp页面中使用标签


(7)运行结果
设置PageContext对象!
设置标签的父标签!
标签开始处理..
标签结束处理..


二、自定义实现IterationTag接口的标签步骤
(1)IterationTag接口简介
IterationTag接口继承自Tag接口,IterationTag接口增加了重复执行标签主体内容的功能。
IterationTag接口定义了一个doAfterBody()方法,Servlet容器在执行完标签主体内容后,会调用此方法。
如果Serlvet容器未执行标签主体内容,那么就不会调用此方法。
doAfterBody()方法也返回一个整数值,用来决定程序后续流程,它有两个可选值:Tag.SKIP_BODY和IterationTag.EVAL_BODY_AGAIN。
Tag.SKIP_BODY表示不再执行标签主体内容;
IterationTag.EVAL_BODY_AGAIN表示重复执行标签主体内容。
(2)Servlet容器执行IterationTag接口的流程
1.Servlet容器调用IterationTag对象的setPageContext()和setParent()方法,把当前JSP页面的PageContext对象及父标签处理对象传给当前IterationTag对象。如果不存在父标签,则把父标签处理对象设为null。
2.Servlet容器调用IterationTag对象的一系列set方法,设置Tag对象的属性。如果标签没有属性,则无需这个步骤。
3.Servlet容器调用IterationTag对象的doStartTag()方法。
4.如果doStartTag()方法返回Tag.SKIP_BODY,就不执行标签主体的内容;如果doStartTag()方法返回Tag.EVAL_BODY_INCLUDE,就执行标签主体的内容。
5.如果在步骤(4)中Servlet容器执行了标签主体的内容,那么就调用doAfterBody()方法。
6.如果doAfterBody()方法返回Tag.SKIP_BODY,就不再执行标签主体的内容;如果doAfterBody()方法返回IterationTag.EVAL_BODY_AGAIN,就继续重复执行标签主体的内容。
7.Servlet容器调用IterationTag对象的doEndTag()方法。
8.如果doEndTag()方法返回Tag.SKIP_PAGE,就不执行标签后续的JSP代码;如果doEndTag()方法返回Tag.EVAL_PAGE,就执行标签后续的JSP代码。
(3)实例代码见ForTagLib类

三、自定义实现BodyTag接口的标签
(1)BodyTag接口简介
BodyTag接口继承自IterationTag接口,增加了直接访问和操纵标签主体内容的功能。BodyTag接口定义了两个方法。
setBodyContent(BodyContent bc):Servlet容器通过此方法向BodyTag对象传递一个用于缓存标签主体的执行结果的BodyConent对象。
doInitBody():当Servlet容器调用完setBodyContent()方法之后,在第一次执行标签主体之前,先调用此方法,该方法用于为执行标签主体做初始化工作。
(2)只要符合以下两种条件之一,setBodyContent(BodyContent bc)和doInitBody()就不会被Servlet容器调用:
1.标签主体为空。
2.doStartTag()方法的返回值为Tag.SKIP_BODY或者Tag.EVAL_BODY_INCLUDE。
只有同时符合以下两个条件,Servlet容器才会调用setBodyContent(BodyContent bc)和doInitBody()方法:
1.标签主体不为空。
2.doStartTag()方法的返回值为BodyTag.EVAL_BODY_BUFFERED。
以上提到的BodyTag.EVAL_BODY_BUFFERED是在BodyTag接口中定义的int类型的静态常量,它可作为doStartTag()方法的返回值,指示Servlet容器调用BodyTag对象的setBodyContent()和doInitBody()方法。
(3)Servlet容器调用BodyTag对象的流程
1.Servlet容器调用BodyTag对象的setPageContext()和setParent()方法,把当前JSP页面的PageContext对象及父标签处理对象传给当前BodyTag对象。如果不存在父标签,则把父标签处理对象设为null。
2.Servlet容器调用BodyTag对象的一系列set方法,设置Tag对象的属性。如果标签没有属性,则无需这个步骤。
3.Servlet容器调用BodyTag对象的doStartTag()方法。
4.如果doStartTag()方法返回Tag.SKIP_BODY,就不执行标签主体的内容;如果doStartTag()方法返回Tag.EVAL_BODY_INCLUDE,就执行标签主体的内容;如果doStartTag()方法返回BodyTag.EVAL_BODY_BUFFERED,就先调用setBodyContent()和doInitBody()方法,再执行标签主体的内容。
5.如果在步骤(4)中Servlet容器执行了标签主体的内容,那么就调用doAfterBody()方法。
6.如果doAfterBody()方法返回Tag.SKIP_BODY,就不再执行标签主体的内容;如果doAfterBody()方法返回IterationTag.EVAL_BODY_AGAIN,就继续重复执行标签主体的内容。
7.Servlet容器调用BodyTag对象的doEndTag()方法。
8.如果doEndTag()方法返回Tag.SKIP_PAGE,就不执行标签后续的JSP代码;如果doEndTag()方法返回Tag.EVAL_PAGE,就执行标签后续的JSP代码。

四、TagSupport类和BodyTagSupport类
TagSupport类和BodyTagSupport类是标签实现类,其中TagSupport类实现了IterationTag接口,而BodyTagSupport类则继承自TagSupport类,并且实现了BodyTag接口。
用户自定义的标签处理类可以继承TagSupport类或者BodyTagSupport类。   

五、创建标签库描述文件
标签库描述文件(Tag Library Descriptor,TLD),采用XML文件格式,对标签库及库中的标签做了描述。TLD文件中的元素可以分为3类:
1.<taglib>:标签库元素。
2.<tag>:标签元素。
3.<attribute>:标签属性元素。

1、标签库元素<taglib>
<taglib>元素的子元素
tlib-version指定标签库的版本
jsp-version 指定JSP的版本
short-name 指定标签库默认的前缀名(prefix)
uri 设定标签库的唯一访问标识符
info 设定标签库的说明信息
2、标签元素<tag>
name 设定标签的名字
tag-class 设定Tag的处理类
body-content 设定标签主体的类型
info 设定标签的说明信息

empty:标签主体为空。
scriptless:标签主体不为空,并且包含JSP的EL表达式和动作元素,但不能包含JSP的脚本元素。所谓动作元素是指<jsp:include>和<jsp:forward>等以“jsp”为前缀的JSP内置标签。所谓脚本元素是指“<%!”和“%>”、“<%”和“%>”和“<%=”和“%>”这3种以“<%”开头的JSP标记。
JSP:标签主体不为空,并且包含JSP代码。在JSP代码中可以包含EL表达式、动作元素和脚本元素。<body-content>子元素的scriptless可选值与jsp可选值的区别在于前者不能包含JSP的脚本元素。
tagdependant:标签主体不为空,并且标签主体内容由标签处理类来解析和处理。标签主体的所有代码都会原封不动的传给标签处理类,而不是把标签主体的执行结果传给标签处理类。假定用户定义了一个<sql:query>标签,它的<body-content>元素的值为tagdependant。
3、标签属性元素<attribute>
name 属性名称
required 属性是否是必须的,默认为false

rtexprvalue 属性值是否可以为基于“<%=”和“%>”形式的Java表达式或者EL表达式

项目下载地址:http://download.csdn.net/detail/afgasdg/3813461


posted @ 2011-11-19 10:12  hibernate3例子  阅读(298)  评论(0编辑  收藏  举报