Ch8中我们学习了传统的自定义标签的开发方法,在传统的自定义标签的主体中可以包含Java程序片段,但是标签的处理流程比较复杂,开发人员需要考虑标签处理类中的doStartTag()和doEndTag()等方法的返回值。为了简化开发标签的过程,JSP2.0 中引入了一种新的标签扩展机制,称为“简单标签扩展”,这种机制有两种使用方式:
- 对于熟悉Java编程语言的开发人员,可以定义实现javax.servlet.jsp.tagext.SimpleTag接口的标签处理类。
- 对于不懂Java编程语言的网页制作者,可以使用标签文件来定义标签。标签文件以.tag或.tagx作为文件扩展名。
1. 实现SimpleTag接口
在javax.servlet.jsp.tagext.SimpleTag接口中定义了以下5个方法:
- void setJspContext(jspContext pc):由Servlet容器调用该方法,向SimpleTag对象传递当前的 JspContext对象。JspContext类是PageContext类的父类,在JspContext类中定义了用于存取各种范围内的共享数据的方法,如getAttribute()、setAttribute()和removeAttribute()方法等,之前介绍PageContext抽象类时,对此作了介绍。
- void setParent(JspTag parent):Servlet容器调用该方法,向当前SimpleTag对象传递父标签的JspTag对象。
- JspTag getParent():返回父标签的JspTag对象。
- void setJspBody(JspFragment jspBody):由Servlet容器调用该方法,向当前SimpleTag对象传递标签主体。参数JspBody表示当前标签的主体,它封装了一段JSP代码。
- void doTag():该方法负责具体的标签处理过程。与传统标签处理类的doStartTag()和doEndTag()方法不同的是,doTag()方法没有返回值。
SimpleTag对象由Servlet容器负责创建,每次当Servlet容器在执行JSP文件时,遇到JSP文件中的自定义的简单标签,都会创建一个SimpleTag对象,当标签处理完毕,就会销毁该SimpleTag对象,这是与传统的自定义标签的一个不同之处,因为传统自定义标签的处理类的实例会被Servlet容器缓存,以便重复利用该实例。
Servlet容器在得到了SimpleTag对象后,会按照下面的流程调用SimpleTag对象的相关方法:
- Servlet容器调用SimpleTag对象的setJspContext()和setParent()方法,把当前JSP页面的JspContext对象及父标签处理对象传给当前SimpleTag对象。如果不存在父标签,则把父标签处理对象设为null。
- Servlet容器调用SimpleTag的一系列set方法,设置SimpleTag对象的属性。
- 如果存在标签主体,Servlet容器就调用SimpleTag对象的setJspBody()方法,设置标签主体。
- Servlet容器调用SimpleTag对象的doTag()方法,在该方法中完成处理标签的具体逻辑。
在开发简单标签时,只需要创建SimpleTagSupport类的子类,然后覆盖其doTag()方法即可。
1.1 创建和使用<hello>简单标签
以下程序HelloTag.java是一个简单标签处理类,它的作用是打印“This is my first tag~”:
mypack/HelloTag.java
package mypack;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
public class HelloTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
JspWriter out = getJspContext().getOut();
out.write("this is my first tag~");
}
}
在
web/WEB-INF/mytaglib.tld文件中配置该tag:
<tag>
<description> Print"This is my first tag~"</description>
<name>hello</name>
<tag-class>mypack.HelloTag</tag-class>
<body-content> empty</body-content>
</tag>
然后在
helloworld.jsp文件中使用该标签:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="mm" uri="/mytaglib" %>
<html>
<head>
<title>SimpleTagTest</title>
</head>
<body>
<mm:hello />
</body>
</html>
运行Web应用,访问helloworld.jsp:
对于简单标签,其<tag>元素的<body-content>子元素的值包括empty、scriptless和tagdependent,默认值为scriptless。相比于传统的自定义标签,简单标签的<body-content>子元素可选值少了一个JSP,这是因为简单标签的主体不能包含Java程序片段等脚本元素。
1.2 创建和使用带属性和标签主体的<welcome>简单标签
下面的例程helloworld.jsp使用了<welcome>简单标签,该标签具有一个username属性,而且具有标签主体。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="mm" uri="/mytaglib" %>
<html>
<head>
<title>SimpleTagTest</title>
</head>
<body>
<mm:hello />
<mm:welcome username="${param.username}">welcome to this page</mm:welcome>
</body>
&l