March 24, 2016
定制标签的目的是分离表现逻辑和业务逻辑,可以在 JSP 页面编写中尽量不出现scriptlet
,而且可以根据自己想要的功能定制属于自己想要的标签,完成特定的功能。
这里只讲在 JSP2.0 之后添加的一个用于编写定制标签的接口—— SimpleTag
,这个接口实现简单,效果也不错。
SimpleTag
接口位于javax.servlet.jsp.tagext
中,实现了该接口的标签处理器称作简单的标签处理器。SimpleTag
接口中只有一个方法:doTag()
,并且在标签调用时只执行一次。业务逻辑及主题操作代码都要在这里编写。
setJspCOntext
方法,同时传递一个JspContext
对象。JspContext
最重要的方法是getOut
,它返回一个JspWriter
,用于将响应发送到客户端。setJspContext
方法的签名如下:public void setJspContext (JspContext jspContext)
大多数时候,需要将传进来的JspContext
对象赋给一个类级变量,便于后续使用。
setParent
方法。该方法的签名如下:public void setParent(JspTag parent)
SimpleTag
接口中的setJspBody
方法,将主体内容作为JspFragment
传递。如果没有主体内容,JSP 容器将不会调用这个方法。doTag
方法。所有变量在doTag
方法返回时同步。注:javax.servlet.jsp.tagext
包中也含有SimpleTag
接口的一个支持类:SimpleTagSupport
。SimpleTagSupport
为SimpleTag
接口中的所有方法都提供了默认实现(类似于适配器),我们可以继承它来编写一个简单的标签处理器。当 JSP 容器调用SimpleTag
接口的setJspContext
方法时,SimpleTagSupport
类中的getJspContext
方法将返回 JSP 容器传递的JspContext
实例。
为了编译标签处理器,需要在构建路径中包含Servlet API
和JSP API
类包。例如Tomcat
的servlet-api.jar
文件和jsp-api.jar
文件。
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class MyFirstTag implements SimpleTag {
JspContext jspContext;
@Override
public void doTag() throws JspException, IOException {
System.out.println("doTag");
jspContext.getOut().print("This is my first tag.");
}
@Override
public JspTag getParent() {
System.out.println("getParent");
return null;
}
@Override
public void setJspBody(JspFragment body) {
System.out.println("setJspBody");
}
@Override
public void setJspContext(JspContext jspContext) {
System.out.println("getJspContext");
this.jspContext = jspContext;
}
@Override
public void setParent(JspTag parent) {
System.out.println("setParent");
}
}
MyFIrstTag
类有一个类型为JspContext
的jspContext
变量。setJspContext
方法将它从 JSP 容器接收到的JspContext
赋给这个变量。doTag
方法利用JspContext
获得一个JspWriter
。然后调用JspWriter
的print
方法,输出This is my first tag.
用一个以.tld
为扩展名的 XML 文件描述标签处理器。以下示例mytags.tld
:
<?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"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_1.xsd"
version="2.1">
<description>
Simple tag examples
</description>
<tlib-version>1.0</tlib-version>
<short-name>My First Taglib Example</short-name>
<tag>
<name>firstTag</name>
<tag-class>customtag.MyFirstTag</tag-class>
<body-content>empty</body-content>
</tag>
<tag>
<name>dataFormatter</name>
<tag-class>customtag.DataFormatterTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>header</name>
<required>true</required>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
</attribute>
</tag>
<tag>
<name>select</name>
<tag-class>customtag.SelectElementTag</tag-class>
<body-content>scriptless</body-content>
</tag>
</taglib>
标签类库描述符中的主要元素是tag
,它用来描述标签,其中包含一个name
元素和一个tag--class
元素。name
用于给该标签命名。tag-class
用于指定标签处理器的全类名。一个.tld
文件中可以包含多个tag
元素。
description
用于描述tag
元素。short-name
为标签的简称。tlib-version
元素设置定制标签的版本。
<%@ taglib uri="WEB-INF/mytags.tld" prefix="easy">
<html>
<head>
<title>测试我的第一个标签</title>
</head>
<body>
Hello!<br/>
<easy:firstTag></easy:firstTag>
</body>
</html>
在控制台上将显示:
setJspContext
doTag