JavaWeb从入门到精通(视频实战版)
上QQ阅读APP看书,第一时间看更新

2.7 自定义JSP标签

前面介绍了JSP的动作标签,使用标签可以处理定向请求以简化JSP页面开发与维护。JSP技术提供了一种封装其他动态类型的机制—自定义标签,它扩展了JSP语言。自定义标签通常发布在标签库中,该库定义了一个自定义标签集并包含实现标签的对象。一些功能可以通过自定义标签来实现,包括对隐含对象的操作,处理表单,访问数据库及其他企业级服务,如e-mail、目录服务、处理流控制。很多JSP开发框架如Struts都提供了丰富的标签库,本节将以一个“Hello Reader”的例子来介绍如何自定义JSP标签。

2.7.1 标签库简介

标签库涉及4个基本概念:

(1)标签(Tag)

标签是一种XML元素,通过标签可以使JSP网页变得简洁并且易于维护,还可以方便地实现同一个JSP文件支持多种语言版本。由于标签是XML元素,所以它的名称和属性都是大小写敏感的。

(2)标签库(Tag Library)

由一系列功能相似、逻辑上互相联系的标签构成的集合称为标签库。

(3)标签库描述文件(Tag Library Descriptor File)

标签库描述文件是一个XML文件,简称TLD文件,这个文件提供了标签库中类和JSP中对标签引用的映射关系。它是一个配置文件,和web.xml是类似的。

(4)标签处理类(Tag Handle Class)

标签处理类是一个Java类,这个类继承了TagSupport或者扩展了SimpleTag接口,通过这个类可以实现自定义JSP标签的具体功能。

开发一个自定义标签,主要工作就是创建TLD文件和编写标签处理类。

2.7.2 创建标签的处理类

标签处理类必须实现Tag接口的doStartTag和doEndTag方法。当JSP引擎碰到tag标签的开头时,doStartTag被调用,因为简单的tag没有body,所以此方法将返回SKIP_BODY。当JSP引擎碰到tag标签的结尾时,doEndTag被调用,如果余下的页面还要被计算,那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。

一般的做法是不必直接实现Tag接口而是实现TagSupport类,如实例2-18中标签的作用是打印字符串“Hello Reader!”。

【实例2-18】自定义标签示例SimpleTag.java

01   package com.book.web3;
02   import javax.servlet.jsp.JspException;
03   import javax.servlet.jsp.JspTagException;
04   import javax.servlet.jsp.tagext.TagSupport;
05   public class SimpleTag extends TagSupport {
06     public int doStartTag() throws JspException {       //实现doStartTag()方法
07        try {
08           pageContext.getOut().print("Hello Reader! ");
09           pageContext.getOut().print("<br> ");
10           pageContext.getOut().print("I'm from custom Tag");
11        } catch (Exception e) {
12           throw new JspTagException("SimpleTag: " + e.getMessage());
13        }
14        return SKIP_BODY;
15     }
16     public int doEndTag() {                     //实现doEndTag()方法
17        return EVAL_PAGE;
18     }
19   }

【代码剖析】上面第5行代码使类SimpleTag继承TagSupport类,然后重写了方法doStartTag()和doEndTag(),前者是在标签开始时触发,而后者则是在标签结束时触发。

2.7.3 创建标签库描述文件

标签库文件简称TLD文件,是用XML语言描述的。TLD包括了标签库中所有标签的描述,它一般被JSP服务器用来校验标签的语法正确性,或者被JSP开发者用来开发新的标签。TLD的文件扩展名必须为.tld,而且必须放在当前Web应用的WEB-INF目录或其子目录中。如实例2-19与上一节中的处理类配合形成一个完整的标签。

【实例2-19】自定义标签的TLD文件helloreader.tld

01   <?xml version="1.0" encoding="ISO-8859-1" ?>
02   <!DOCTYPE taglib
03    PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
04    "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
05   <taglib>
06    <tlibversion>1.0</tlibversion>
07    <jspversion>1.1</jspversion>
08    <shortname>hellodemo</shortname>
09    <tag>
10      <name>hello</name>
11      <tagclass>com.book.web3.SimpleTag</tagclass>
12      <bodycontent>empty</bodycontent>
13    </tag>
14   </taglib>

【代码剖析】上面第6行代码定义了Tag库的版本,第7行代码定义了该标签所需要的JSP版本,第8行代码为标签设置一个别名,最后通过<tag>标签来具体定义标签。

<taglib>包含的子元素见表2.10。

表2.10 taglib的子元素表

listener元素是一个tag库,可以定义一些类作为它的事件侦听类,JSP服务器将会实例化这些侦听类,并且注册它们。listener元素中有一个叫listener-class的子元素,这个元素的值必须是该侦听类的完整类名。

每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略、它的值是否可以通过<%=⋯%>这样的JSP语法来获得,以及属性的类型。

每一个tag在TLD中对应一个tag元素,表2.11所示是tag元素的子元素。

表2.11 tag的子元素表

2.7.4 使用自定义标签

首先要配置web.xml,使用自定义标签<taglib>。

<taglib-uri>/WEB-INF/ helloreader.tld</taglib-uri>
<!--加载标签, 供页面中使用-->
  <taglib-location>/WEB-INF/ helloreader.tld</taglib-location>
</taglib>

在JSP中引用标签,如实例2-20所示。

【实例2-20】显示自定义标签

01   <%@ taglib uri="/WEB-INF/helloreader.tld" prefix="demo"%>
02   <html>
03     <head>
04        <title>Tag Test</title>
05     </head>
06     <body>
07        <h1>
08          <demo:hello />               <!--使用自定义标签-->
09        </h1>
10     </body>
11   </html>

【运行程序】浏览该页面,结果如图2.25所示。

【代码剖析】上面第8行代码输出自定义标签。

图2.25 自定义标签结果图

2.7.5 JSP 2.0中新增的标签定义方法

JSP 2.0提供一些较为简单的方法,让开发人员来撰写自定义标签。JSP 2.0提供两种新的机制,分别为Simple Tag和Tag File。

SimpleTagSupport类别顾名思义,就是可以处理一些简单的自定义标签需求,它是在JSP 2.0之后新增的类别。对于一些简单的自定义标签需求,您可以继承它来实现标签处理类别,这样就不用处理一些TagSupport、BodyTagSupport类别中回传值的问题。

另一方面就是SimpleTagSupport类别所处理的功能受了些限制,它只处理标签与本体,要不要显示本体文字取决于您。对于标签之后的页面则不在SimpleTagSupport处理的范围之内(虽然还是可以使用forward之类的方式来决定要不要显示之后的页面,但直接实现TagSupport会更方便一些)。另外,SimpleTagSupport类别的本体文字不能设定为JSP,这也是使用SimpleTagSupport上的一些限制。Simple-Tag Handler和其他Tag Handler(如Body Tag Handler、Tag Handler和Iteration Tag Handler)不同之处在于:Simple Tag Handler并无doStartTag( )和doEndTag( ),它只有doTag( ),因此,实现标签能比以往更为方便。

Tag File就更为简单,可以把它当做直接使用JSP的语法来制作标签。例如:

Hello.tag

<%
out.println("Hello from tag file.");
%>

先制作一个名为Hello.tag的Tag File,然后将它放置在WEB-INF/tags/目录下。

<%@ taglib prefix="myTag" tagdir="/WEB-INF/tags" %>
<myTag:Hello />

最后执行的结果如下:

Hello from tag file.

注意 在JSP网页使用TagFile时引用的是路径而非文件名。