用五个容易的步骤实现 JSP 自定义标记
JSP 自定义标记
JSP 自定义标记是用户定义的标记,它遵循 JSP JavaBean 标记(即 useBean 、 getProperty 和 setProperty )所使用的一种特殊的 XML 语法。当 servlet 容器处理自定义标记时,会调用一个或者多个 Java 类文件处理它,与用 Java 类文件处理 JSP 页面的 JavaBean 调用的方式基本一样。处理标记以后,容器将取其名字和属性、以及标记正文中可能有的任何内容,并将它传递给一个或者多个类文件进行处理。
Java 开发人员编写标记处理程序类以处理标记并处理所有需要的 Java 代码和数据操作。对于 Web 设计者来说,自定义标记与标准 HTML 标记除了都可以利用后端动态数据外,它们看上去与使用起来没什么区别。正确编写自定义标记可以让 Web 设计者创建、查询和操作数据而无需编写一行 Java 代码。正确使用自定义标记使 Java 开发人员不必再在编码过程中考虑表示层。这样应用程序开发小组的每一位成员都可以关注于他或者她最擅长的事物。
实现 JSP 自定义标记
JSP 体系结构需要以下组件以实现自定义标记:
在每一页中有一个 JSP 声明
Web 应用程序描述符(l)中的一个项
一个包含特殊 XML 文件和为处理自定义标记而调用的 Java 类的 JAR 文件
在下面几节,您将一步一步地学习如何满足这些要求并将自定义标记加入到 JSP 页面中。要想成功实现 JSP 自定义标记,您需要采取下面五个步骤:
编写标记处理程序类。
创建标记库描述符(TLD)。
使 TLD 文件和处理程序类可访问。
引用标记库。
在 JSP 页面中使用标记。
这些内容是相当基本的,也不用花很长时间。就让我们开始吧。
第1步. 编写标记处理程序类
在下面的例子中,我们将使用一个非常简单的显示当前时间和日期的自定义标记例子。下面就是 DateTag :
1 <abc:displayDate />
2
2
我们要做的第一件事是编写标记处理程序类。在执行引用自定义标记的 JSP 页面时,JSP 容器判断每一个自定义标记。当容器遇到一个标记时,它调用与这个自定义标记相关联的标记处理程序,我们将在后面更多地讨论这个过程。然后,每一个标记处理程序实现 JSP API 中的一个特殊接口。标记有两种类型:可以处理标记内容(或者正文)的标记和不能处理标记内容的标记:
1 <abc:tagWithNoBody attribute="value"/>
2 <abc:tagWithBody attribute="value">
2 <abc:tagWithBody attribute="value">
3 This is some body content that the tag handler can operate upon.
4 </abc:tagWithBody>
4 </abc:tagWithBody>
在 DateTag 例子中不需要加入正文内容,因为它只显示当前日期。因此,我们的处理程序类将实现 Tag 接口(一般是通过扩展 TagSupport 类)。如果我们要创建一个可以处理正文的标记,那么我们就需要实现 BodyTag 接口(一般是通过扩展 BodyTagSupport 类)。清单 1 显示了 DateTag 的处理程序类:
清单 1. 标记处理程序类
1 package myTags;
2 import javax.servlet.jsp.tagext.*;
3 import javax.servlet.jsp.*;
4 import javax.servlet.http.*;
5 import *;
6 jsp创建import java.util.*;
7 public DateTag extends TagSupport {
2 import javax.servlet.jsp.tagext.*;
3 import javax.servlet.jsp.*;
4 import javax.servlet.http.*;
5 import *;
6 jsp创建import java.util.*;
7 public DateTag extends TagSupport {
8
9 public int doStartTag() throws javax.servlet.jsp.JspException {
10 HttpServletRequest req;
11 Locale locale;
12 HttpJspPage g;
13 DateFormat df;
14 String date;
15 JSPWriter out;
16
17 req = ( HttpServletRequest )Request();
18 locale = Locale();
19 df = DateInstance(
20 SimpleDateFormat.FULL,locale );
21 date = df.format( new java.util.Date() );
22
9 public int doStartTag() throws javax.servlet.jsp.JspException {
10 HttpServletRequest req;
11 Locale locale;
12 HttpJspPage g;
13 DateFormat df;
14 String date;
15 JSPWriter out;
16
17 req = ( HttpServletRequest )Request();
18 locale = Locale();
19 df = DateInstance(
20 SimpleDateFormat.FULL,locale );
21 date = df.format( new java.util.Date() );
22
23 try {
24 out = Out();
25 out.print( date );
26 } catch( IOException ioe ) {
27 throw new JspException( "I/O Error : " + Message() );
28 }//end try/catch
29 return Tag.SKIP_BODY;
30 }//end doStartTag()
31 }//end DateTag
32
24 out = Out();
25 out.print( date );
26 } catch( IOException ioe ) {
27 throw new JspException( "I/O Error : " + Message() );
28 }//end try/catch
29 return Tag.SKIP_BODY;
30 }//end doStartTag()
31 }//end DateTag
32
关于这段代码的说明
关于 DateTag 处理程序类有几件事值得一说。首先看一下方法声明。如果我们直接实现 Tag 接口,那么就需要完成几个方法声明。因为 TagSupport 类是简单的、具体类,它完全实现了在 Tag 接口中声明的方法,我们可以只实现那些在自定义标记中要使用的方法。在这个简单的例子中,我们只实现了 doStartTag() 方法,它是在遇到开始标记时调用的。
您还可能注意到 doStartTag() 方法返回 SKIP_BODY 。当然其原因是我们的简单日期标记没有正文。您要注意的最后一件重要的事情是使用了 pageContext 对象访问输出缓存以直接向输出流发送内容。您可能还记得在本系列以前的文章说过, pageContext 对象是一个隐式对象,它提供对与当前页面有关的属性的访问。
编写了源代码文件后,我们像编译所有其他 Java 类一样编译这个类(确保在类路径中加入 Servlet/JSP JAR 文件),然后将编译的类文件放到 Web 应用程序的类目录(WEB-INF/classes)中。如果我们开发的是几个标记或者定义有标记变量的标记,那么我们就会有多个标记处理程序类。在这种情况下我们可能选择将处理程序类打包在一个 JAR 文件中而不是使它们成为类目录中的分散的文件。
第2步. 创建 TLD
下一步是定义包含自定义标记与处理它的 Java 类(或多个类)之间的映射的库。这个库是在一个名为标记库描述符(TLD)的 XML 文档中定义的。我们将从 DateTag 例子 DateTagLib.tld中调用这个 TLD。注意“.tld”是这种文件的标准扩展名。
清单 2. DateTagLib.tld 文件
1 <?xml version="1.0" encoding="ISO-8859-1" ?>
2 <taglib>
3 <tlibversion>1.0</tlibversion>
4 <info>A simple tag library</info>
5 <tag>
6 <name>displayDate</name>
7 <tagclass>myTags.DateTag</tagclass>
8 <bodycontent>empty</bodycontent>
9 <info>Display Date</info>
10 </tag>
11 </taglib>
12
2 <taglib>
3 <tlibversion>1.0</tlibversion>
4 <info>A simple tag library</info>
5 <tag>
6 <name>displayDate</name>
7 <tagclass>myTags.DateTag</tagclass>
8 <bodycontent>empty</bodycontent>
9 <info>Display Date</info>
10 </tag>
11 </taglib>
12
DateTagLib.tld 是一个出的、最小的标记库描述符文件。所有关键信息都包含在 Tag 标记中,在这里映射了标记名和处理程序类,我们声明了标记对于正文内容的敏感性。对于更复杂的情况,我们可以使用其他的 XML 标记以提供有关库和标记的更多信息。在一个库
中定义多个标记也很常见。
第3步. 使 TLD 和处理程序类可访问
第 3 步是使这个类或者这些类和 TLD 可以被 Web 应用程序访问。有两种方法:可以将类和 TLD 打包到一个 JAR 文件中,再将这个 JAR 文件储存在 Web 应用程序的 lib 目录中,也可以将类文件分散地放到 classes 子目录中并将 TLD 文件放到 Web 应用程序的 WEB-INF 目录下面的某一位置。
在这个例子中,我们将使用第二种方法,将 TLD 文件和类分散地放到 Web 应用程序目录结构中。您可以回忆起在第 1 步中我们已经将标记处理程序类放到了 classes 目录中,所以我们实际上只需储存 TLD 文件。TLD 文件被储存在 WEB-INF 目录或者子目录中,如果是部署 Java 文件,则储存在 JAR 的 META-INF/ 目录或者子目录。在这里,我们没有使用 JAR 文件,所以我们只将 TLD 储存到 Web 应用程序的 WEB-INF/lib 目录中。
第4步. 引用这个库
这时,我们已经编译了标记处理程序类、创建了 TLD 文件以定义处理程序类和标记之间
的映射、并保证类和标记在应用程序中都是可访问的。下一步是建立 JSP 页面与标记库之间的引用。有两种方法声明 JSP 页面与其库之间的引用。可以通过 Web 应用程序描述符(l)声明一个静态引用,也可以直接在页面中声明一个动态引用。我们将试用这两种方法。
为了进行静态引用,首先必须将下面的项加入到 l 文件中:
1 <?xml version="1.0" encoding="ISO-8859-1" ?>
2 <Web-app>
3
4
5
6 <taglib>
7 <taglib-uri>myTags</taglib-uri>
8 <taglib-location>/WEB-INF/lib/DateTagLib.tld</taglib-location>
9 </taglib>
2 <Web-app>
3
4
5
6 <taglib>
7 <taglib-uri>myTags</taglib-uri>
8 <taglib-location>/WEB-INF/lib/DateTagLib.tld</taglib-location>
9 </taglib>
10
11 </Web-app>
12
11 </Web-app>
12
然后,将 JSP 声明加入到所有需要使用自定义标记库的页面中:
1 <%@ taglib uri="myTags" prefix="abc" %>
2
2
注意指定的 uri 属性与在 l 文件中指定的 taglib-uri 值相匹配。
为了进行动态引用,只需在所有需要使用这个库的页面中加入一个 JSP 声明即可:
1 <%@ taglib uri="/WEB-INF/lib/DateTagLib.tld" prefix="abc" %>
2
2
静态引用与动态引用的比较
在进行标记库的静态引用时,JSP 声明必须查询 l 文件以执行库查询。这意味着
如果移动或者重命名了库,或者希望在 l 文件中加入更多的库,就必须停止服务器、更新 l 文件、然后重新启动服务器。动态方法让 JSP 页直接指向 TLD 位置,因而是在解释 JSP 页面时进行处理。
静态方法提供了页面与库的实际名和位置之间一定程度的非直接性,这可以为您提供一些改变这些属性而不修改页面的灵活性。另一方面,动态方法提供了更大的灵活性,让您可以在运行时增加和移动标记声明。如果您对动态方法感兴趣,但是又担心做了一些改变后、有可能要更新多个页面的维护负担,那么您可以始终将 JSP 声明放到一个单独的 JSP 文件中,并在每一个要访问 Web 应用程序的自定义库的页面中加入这一页。这使您具有在运行时只需要更新信息一次就可以增加库的灵活性。
第 5 步. 在 JSP 页面中使用标记
完成了所有这些准备工作后,我们就可以在 JSP 页面中使用这些自定义标记了。清单 3 显示了包含 DateTag 的 JSP 页面的浏览器输出:
清单 3. 带有自定义标记的 JSP 页
1 <%@ taglib uri="/WEB-INF/lib/DateTagLib.tld" prefix="abc" %>
2 <HTML>
3 <HEAD>
4 <TITLE>Date tag example</TITLE>
5 </HEAD>
6
7 <BODY>
8 <H1>Date tag Example</H1>
9 <p>Hi today is <b><abc:displayDate /></b> </p>
10 </BODY>
11 </HTML>
12
2 <HTML>
3 <HEAD>
4 <TITLE>Date tag example</TITLE>
5 </HEAD>
6
7 <BODY>
8 <H1>Date tag Example</H1>
9 <p>Hi today is <b><abc:displayDate /></b> </p>
10 </BODY>
11 </HTML>
12
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论