1、自定义标签的概念
目前我们在JSP中使用的标签都是HTML的标签,浏览器会自动解析运行,例如<form action=""></form>,这里的form就是标签名称,action即form标签的属性,而<form></form>之间的内容,我们称之为标签体。
而自定义标签,就是可以根据需求,自己定义的标签,不论是标签的名字,属性,还是作用等等。使用自定义标签,可以把很多重复的代码或相似的功能封装起来,在JSP中就可以直接以标签使用,使JSP文件结构简练,可读性强,可维护性也强。
2、自定义标签的基本组成
自定义标签分为两个部分:
- *.tld :(taglib descriptor)这是一个xml格式的文件,用来定义标签名称、属性、标签处理类、标签体等
- *.class :每个标签会有对应的处理类,这个类要遵守一定的规范(继承或实现API中特定类或接口,覆盖方法)
也即是说,自定义标签的功能无非还是使用Java类来实现的,不过Java代码不再直接写到JSP中,而是用Java类实现,在JSP则以更简练的标签进行调用,以达到复用。
3、自定义标签的实例
下面实现这样一个简单的自定义标签,功能是:获取一个请求范围的属性的值并显示,如果该值为空,则显示字符串”该值不存在“。
3.1 创建tld文件
tld文件就是一个xml格式的文件,不过里面需要符合一些tld的格式规范,具体的可以参考《tld格式规范》,也可以下载相关的dtd(DTD可定义合法xml文档构建模块,定义文档结构,详情参考DTD简介)。
按照格式在tld文件中进行标签描述之后,需要将该tld文件存放在WEB-INF目录下:
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<display-name>Demo Tag</display-name>
<tlib-version>1.0</tlib-version>
<short-name>d</short-name>
<!--资源定位符,并不一定真实存在的路径,保持唯一即可-->
<uri>/dulk/learn/demo/taglib</uri>
<!--tag,开始标签描述,可以设置多个-->
<tag>
<!--标签描述-->
<description><![CDATA[演示自定义标签]]></description>
<!--标签名称-->
<name>printAttr</name>
<!--标签处理类-->
<tag-class>dulk.learn.demo.PrintAttrHandler</tag-class>
<!--标签体的内容-->
<body-content>empty</body-content>
<!--开始标签属性描述,可以设置多个-->
<attribute>
<!--属性描述-->
<description><![CDATA[需要显示的请求中的属性名称]]></description>
<!--属性名称-->
<name>attr</name>
<!--属性必需性-->
<required>true</required>
<!--runtime expression value 运行期表达式的值,即是否可以传表达式,变量-->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
37
1
2
3
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
4
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
version="2.0"
6
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
7
8
<display-name>Demo Tag</display-name>
9
<tlib-version>1.0</tlib-version>
10
<short-name>d</short-name>
11
<!--资源定位符,并不一定真实存在的路径,保持唯一即可-->
12
<uri>/dulk/learn/demo/taglib</uri>
13
14
<!--tag,开始标签描述,可以设置多个-->
15
<tag>
16
<!--标签描述-->
17
<description><![CDATA[演示自定义标签]]></description>
18
<!--标签名称-->
19
<name>printAttr</name>
20
<!--标签处理类-->
21
<tag-class>dulk.learn.demo.PrintAttrHandler</tag-class>
22
<!--标签体的内容-->
23
<body-content>empty</body-content>
24
<!--开始标签属性描述,可以设置多个-->
25
<attribute>
26
<!--属性描述-->
27
<description><![CDATA[需要显示的请求中的属性名称]]></description>
28
<!--属性名称-->
29
<name>attr</name>
30
<!--属性必需性-->
31
<required>true</required>
32
<!--runtime expression value 运行期表达式的值,即是否可以传表达式,变量-->
33
<rtexprvalue>true</rtexprvalue>
34
</attribute>
35
</tag>
36
37
</taglib>
3.2 创建标签处理器类
标签的处理器类必须继承或实现API中的类,覆盖特定的方法,这里有很多种方式可以实现,示例中采用继承TagSupport类的方法,并覆盖其中的doStartTag方法。
处理器类还必须满足条件:tld文件中包含的属性,该类中必须提供同名属性,并拥有setXxx方法用以属性注入
public class PrintAttrHandler extends TagSupport {
//声明与tld文件中对应的属性
private String attr;
//属性提供set方法
public void setAttr(String attr) {
this.attr = attr;
}
//覆盖父类方法,实现标签功能
@Override
public int doStartTag() throws JspException {
//使用从父类继承到的pageContext对象,可以获取请求/会话/上下文等关键对象
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
JspWriter jspOut = pageContext.getOut();
String value = request.getParameter(attr) == null ? "该值不存在" : request.getParameter(attr);
try {
jspOut.println(value);
} catch (IOException e) {
e.printStackTrace();
}
return super.doStartTag();
}
}
24
1
public class PrintAttrHandler extends TagSupport {
2
//声明与tld文件中对应的属性
3
private String attr;
4
5
//属性提供set方法
6
public void setAttr(String attr) {
7
this.attr = attr;
8
}
9
10
//覆盖父类方法,实现标签功能
11
12
public int doStartTag() throws JspException {
13
//使用从父类继承到的pageContext对象,可以获取请求/会话/上下文等关键对象
14
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
15
JspWriter jspOut = pageContext.getOut();
16
String value = request.getParameter(attr) == null ? "该值不存在" : request.getParameter(attr);
17
try {
18
jspOut.println(value);
19
} catch (IOException e) {
20
e.printStackTrace();
21
}
22
return super.doStartTag();
23
}
24
}
以上通过继承得到了pageContext对象,我们能通过这个对象进而获取到其他内置对象进行使用。
3.3 使用实例
<%@page pageEncoding="utf-8" %>
<!--标签引入-->
<%@taglib uri="/dulk/learn/demo/taglib" prefix="dulk"%>
<html>
<body>
<h2>Hello World!</h2>
<!--标签使用-->
request中author属性的值为:<dulk:printAttr attr="author"/>
</body>
</html>
x
1
<%@page pageEncoding="utf-8" %>
2
<!--标签引入-->
3
<%@taglib uri="/dulk/learn/demo/taglib" prefix="dulk"%>
4
<html>
5
<body>
6
<h2>Hello World!</h2>
7
8
<!--标签使用-->
9
request中author属性的值为:<dulk:printAttr attr="author"/>
10
11
</body>
12
</html>
使用效果: