自定义标签主要用于移除
Jsp
页面中的
java
代码
移除
jsp
页面中的
java
代码,只需要完成两个步骤:
•
编写一个实现
Tag
接口的
Java
类,并覆盖
doStartTag
方法,把
jsp
页面中的
java
代码写到
doStartTag
方法中。
•
编写标签库描述符(
tld
)文件,在
tld
文件中对自定义标签进行描述。
•
完成以上操作,即可在
JSP
页面中导入和使用自定义标签。
Tag接口的执行流程
l
JSP
引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照
JSP
规范定义的通信规则依次调用它的方法。
1、public voidsetPageContext(PageContext pc),JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。
2、public void setParent(Tag t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null。
3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法。
4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。
5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法。
自定义标签功能扩展
l
自定义标签除了可以移除
Jsp
页面中的
java
代码外,它还可以用于完成一些页面逻辑,例如:
•
通过自定义标签可以控制
jsp
页面某一部分内容是否执行。
•
例如:
<c:if>
标签
•
通过自定义标签可以控制标签后的
jsp
页面是否执行。
•
通过自定义标签可以控制
jsp
页面某一部分内容重复执行。
•
例如:
<c:foreach>
标签
•
通过自定义标签可以修改
jsp
页面内容输出。
•
ltld文件中的四种标签体类型
•
EMPTY JSP scriptless tagdepentend
注:左边部分为传统标签,右边为简单标签
简单标签
l
由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广,
SUN
公司为降低标签技术的学习难度,在
JSP 2.0
中定义了一个更为简单、便于编写和调用的
SimpleTag
接口来实现标签的功能。实现
SimpleTag
接口的标签通常称为简单标签。简单标签共定义了
5
个方法:
•
setJspContext
方法
•
setParent
和
getParent
方法
•
setJspBody
方法
•
doTag
方法
l
setJspContext
方法
•
用于把
JSP
页面的
pageContext
对象传递给标签处理器对象
l
setParent
方法
•
用于把父标签处理器对象传递给当前标签处理器对象
l
getParent
方法
•
用于获得当前标签的父标签处理器对象
l
setJspBody
方法
•
用于把代表标签体的
JspFragment
对象传递给标签处理器对象
l
doTag
方法
•
用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在
doTag
方法中可以抛出
javax.servlet.jsp.SkipPageException
异常,用于通知
WEB
容器不再执行
JSP
页面中位于结束标记后面的内容,这等效于在传统标签的
doEndTag
方法中返回
Tag.SKIP_PAGE
常量的情况。
SimpleTag接口方法的执行顺序
l
当
web
容器开始执行标签时,会调用如下方法完成标签的初始化
•
WEB
容器调用标签处理器对象的
setJspContext
方法,将代表
JSP
页面的
pageContext
对象传递给标签处理器对象。
•
WEB
容器调用标签处理器对象的
setParent
方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,
WEB
容器才会调用这个方法。
•
如果调用标签时设置了属性,容器将调用每个属性对应的
setter
方法把属性值传递给标签处理器对象。如果标签的属性值是
EL
表达式或脚本表达式,则
WEB
容器首先计算表达式的值,然后把值传递给标签处理器对象。
•
如果简单标签有标签体,容器将调用
setJspBody
方法把代表标签体的
JspFragment
对象传递进来。
l
执行标签时:
•
容器调用标签处理器的
doTag()
方法,开发人员在方法体内通过操作
JspFragment
对象,就可以实现是否执行、迭代、修改标签体的目的。
JspFragment类
l
javax.servlet.jsp.tagext.JspFragment
类是在
JSP2.0
中定义的,它的实例对象代表
JSP
页面中的一段符合
JSP
语法规范的
JSP
片段,这段
JSP
片段中不能包含
JSP
脚本元素。
l
l
WEB
容器在处理简单标签的标签体时,会把标签体内容用一个
JspFragment
对象表示,并调用标签处理器对象的
setJspBody
方法把
JspFragment
对象传递给标签处理器对象。
JspFragment
类中只定义了两个方法,如下所示:
l
getJspContext
方法
•
用于返回代表调用页面的
JspContext
对象
.
l
publicabstract void invoke(java.io.Writer out)
•
用于执行
JspFragment
对象所代表的
JSP
代码片段
参数
out
用于指定将
JspFragment
对象的执行结果写入到哪个输出流对象中,如果传递给参数
out
的值为
null
,则将执行结果写入到
JspContext.getOut()
方法返回的输出流对象中。
(
简而言之,可以理解为写给浏览器
invoke方法详解
l
JspFragment.invoke
方法可以说是
JspFragment
最重要的方法,利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出。例如:
•
在标签处理器中如果没有调用
JspFragment.invoke
方法,其结果就相当于忽略标签体内容;
•
在标签处理器中重复调用
JspFragment.invoke
方法,则标签体内容将会被重复执行;
•
若想在标签处理器中修改标签体内容,只需在调用
invoke
方法时指定一个可取出结果数据的输出流对象(例如
StringWriter
),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。
开发带属性的标签
l
自定义标签可以定义一个或多个属性,这样,在
JSP
页面中应用自定义标签时就可以设置这些属性的值,通过这些属性为标签处理器传递参数信息,从而提高标签的灵活性和复用性。
l
要想让一个自定义标签具有属性,通常需要完成两个任务:
•
在标签处理器中编写每个属性对应的
setter
方法
•
在
TLD
文件中描术标签的属性
l
为自定义标签定义属性时,每个属性都必须按照
JavaBean
的属性命名方式,在标签处理器中定义属性名对应的
setter
方法,用来接收
JSP
页面调用自定义标签时传递进来的属性值。例如属性
url
,在标签处理器类中就要定义相应的
setUrl(String url)
方法。
l
在标签处理器中定义相应的
set
方法后,
JSP
引擎在解析执行开始标签前,也就是调用
doStartTag
方法前,会调用
set
属性方法,为标签设置属性。
l
在TLD中描述标签属性
<tag>元素的<attribute>子元素用于描述自定义
标签的一个属性,自定义标签所具有的每个属性
都要对应一个<attribute>元素 。
<attribute>
<description>description</description>
<name>aaa</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>ObjectType</type>
</attribute>
如果不知tld文件如何写,可到D:\app\apache-tomcat-7.0\webapps\examples\WEB-INF\jsp目录下的示例tld文件做参考
自定义标签打包
新建一个Java Project,将所写的java标签处理类(包括包名)拷贝到该工程,在根目录下新建一个META-INF目录,将tld文件放到该目录下,然后以jar包(去掉描述IDE环境的配置文件,如eclipse下有.classpath,.project等)的形式导出该Project即可。