J2EE PLATFORM WEB组件开发涉及SERVLET 和JSP技术,SERVLET和JSP各有其优缺点。JVAVABEAN和定制标签对JSP的表示能力提供了很好的扩展,大大提高了JSP的表示能力,同时它们的引入使WEB开发可以很好的进行分工,提高开发效率,降低开发成本,同时提高了JSP页面的可读性、重用性、可维护性。本文将介绍J2EE平台WEB组件开发中如何使用定制标签,主要介绍开发定制标签的意义,原理、步骤、在TOMCAT上的发布并给出一个典型的标签实例以加深理解和提高实战性。引用请保留作者和文章来源
关键词:
J2EE、SERVLET、JSP、WEB组件、定制标签。
一、 为什么要使用定制标签?
开发过Servlet和JSP的人都知道,从表示层来看,Servlet和JSP 是J2EE 平台两中生成动态WEB内容的技术,它们都能产生相同的结果,但它们采用了不同的机制来建立WEB组件。Sverlet是在逻辑中嵌入内容,并夹带服务器方处理逻辑,而JSP是在内容中嵌入逻辑。
JSP像HTML一样是标签化的,适合内容的表示和描述,但需要JAVA脚本才能处理表示逻辑和业务逻辑,然而JAVA代码的嵌入大大降低了JSP页面表示代码的可读性和可维护性,也不利于重复功能的可复用性。同样的Servlet是实现特定接口的JAVA类,它是用JAVA语言写的,是高度编程的,它适合处理表示逻辑和业务逻辑,但在Servlet内加入表示和描述内容的页面代码,一方面使逻辑处理混乱,可读性差,另一方面也给表示内容的维护带来不利。
JavaBean的引入很好的解决了JSP和Servlet面临的两难处境,使J2EE平台WEB组件的开发很好的实现了内容和表示逻辑、业务逻辑的分离。可以高度剥离JSP页面层的JAVA代码、业务逻辑层次的内容描述和表示代码。
但JavaBean存在先天的不足,它只是可复用组件,独立于运行环境而包装了一些数据和业务逻辑功能,无法获得运行环境信息。
在JSP 1.1和 JSP1.2 中相继引入了定制标签这种机制,解决了JavaBean的这种缺陷,从而彻底解决了WEB组件开发中的表示和业务逻辑代码的分离,大大增强了代码的可读性、可维护性、可复用性。
二、 JSP页面与定制标签之间的通讯
在JSP 1.1引入了包javax.servlet.jsp.tagext,定制标签时需要实现特定的接口或继承相应的类,其中Tag接口定义了JSP页面和标签处理器之间基本的通讯合约,即通讯的API接口。JSP规范中规定了WEB容器调用这些方法处理它们通讯的流程,从而实现对标签的生命周期的管理,其时序图如下:
三、 定制标签的原理
1、 定制标签运行所需的四个组件
定制标签需要开发四个组件以确保其能正常运行,它们是:
TagName.class:通常称之为标签处理器,它是实现标签功能的JAVA类。它必须实现特定的JAVA 接口,这些接口和抽象类在包javax.servlet.jsp.tagext中,实现对标签的生命周期的管理。
TaglibName.tld:定义一个标签库的XML文件。其中定义了标签库的名称、版本信息、描述信息和包含的各标签的名称、对应的标签处理器,标签的属性等。
Web.xml :是每个WEB应用程序的唯一的部署描述符文件(每个WEB容器有多个WEB应用程序,但每个WEB应用程序只有一个部署描述符文件)。它是使用XML(Extensible Markup Language)语言写的,描述WEB应用程序可用的资源和相关的信息,一般它在WEB服务器启动时被加载到内存中。WEB服务器依此来调度资源响应用户的请求。必须在Web.xml中注册定制标签库。
JspPage.jsp :是一个JSP页面,该页面使用在WEB应用程序描述符文件中注册的标签库中的标签,实现特定的表示功能。在JSP页面中使用某个标签库之间前,一定要导入标签库。
2、 定制标签处理器实现的接口
以上是定制标签的层次结构图,定制标签可以通过实现其中任何一个接口或者继承任何一个抽象类来实现特定的表示功能。通常使用什么接口或者抽象类处决于开发人员必须定义的方法所预期的生命周期。下面对图中的接口和抽象类分别进行介绍。
javax.servlet.jsp.tagext.Tag接口:
Tag接口定义了标签处理器和调用实例JSP页面之间基本的通讯协议,如果选择实现该接口,要求实现如下定义的所有方法,如:setPageContext(PageContext pc)、setParent(Tag tag)、getParent(Tag tag)、doStartTag()、doEndTag()、release(),这些方法都是容器回调方法。实现Tag接口的标签的生命周期如下图所示。
javax.servlet.jsp.tagext.IterationTag接口:
由上述标签处理器实现接口的层次结构图可知IterationTag接口扩展了Tag接口,而且增加了额外的方法doAfterTag()。该方法使实现该接口的标签处理器能够多次执行标签体正文。如果选择实现该接口,除了要实现Tag中的所有方法外,还要实现doAfterTag(),使标签处理器能够多次执行标签正文。实现IterationTag接口的标签的生命周期如下图所示。
javax.servlet.jsp.tagext.BodyTag接口:
BodyTag扩展了接口IterationTag接口,并且提供了多次执行和修改标签正文的能力。如增加了方法setBodyContent(BodyContent bc)、doInitBody()。IterationTag和BodyTag常用于处理集合对象中的数据实现。BodyTag接口的标签的生命周期如下图所示。
一般情况,用户可以根据实际情况选择地实现上述三个接口之一就能满足需要。但通过实现上述接口开发标签处理器要实现众多地方法是很不方便而且工作量很大,同时功能也受限。不过用户放心,JAVA天生的简洁之美和开放特性是不会让大家失望的,为了简化用户的开发和提供更多额外的功能,javax.servlet.jsp.tagext包还额外的提供了一些支持类,如:
javax.servlet.jsp.tagext.TagSupport
javax.servlet.jsp.tagext.BodyTagSupport
javax.servlet.jsp.tagext.TagExtraInfo
其中TagSupport和BodyTagSupport都实现了Tag接口。TagSupport用于实现那些不需要操纵标签体的的标签处理器;BodyTagSupport用于实现那些要求改变标签正文的标签处理器的标签。TagExtraInfo用于提供编译时标签的额外信息。
四、 基本的定制标签的步骤
定制标签通常有五个步骤:1、编写标签处理器类文件;2、编写标签库描述文件;3、部署标签库;4、向WEB应用程序注册标签库;5、导入和使用标签库。
下面分别加以简单介绍。
1、 标签处理器类文件的编写:
像其它的JAVA组件编程一样,编写标签处理器只需要实现特定的接口就可以了,在上述定制标签的原理中已经详细讨论了如何开发标签处理器,在此不再多说。
2、 编写标签库描述文件:
标签库是一些标签的集合,它们通常有一定的联系。由于标签处理器的方法有很多是容器回调方法,编写完标签后,要向WEB容器提供关于标签的信息,才能在客户引用时,WEB容器知道怎样调用相应的方法来处理客户的请求。通常标签的信息存储在一个名叫TLD的标签库描述文件中。TLD文件是用XML编写,很易理解。该文件一般包含标头信息、标签库定义信息、一个或多个标签定义信息。一个完整的TLD文件如下。
//标头信息
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
//标签库定义信息
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name> customTags </short-name>
<description>A set of my tag handlers.</description>
//标签定义信息
<tag>
<name>tagname</name>
<tag-class>TagHandlerclassName</tag-class>
<attribute>
<name>attributename</name>
<required>true/false</required>
<rtexprvalue>true/false</rtexprvalue>
</attribute>
------
</taglib>
3、 部署标签库:
由于标签库使用TLD文件来描述的,因而部署标签库实际上就是发布TLD文件,一般它放在WEAR包的WEB-INFO文件夹下,即直接将TLD文件拷贝到WEB-INFO文件夹中。
4、 向WEB应用程序注册标签库:
向WEB应用程序注册标签库实际上是向WEB应用程序指出标签库描述文件TLD文件的路径,也就是在WEB.XML文件中指出标签库描述文件的路径(在基于JAVA的WEB组件开发中WEB.XML文件用于向应用程序注册资源信息)。即在其中增加如下语句。
<taglib>
//标签库引用名称
<taglib-uri>/ customTags </taglib-uri>
//标签库描述文件TLD路径
<taglib-location>/WEB-INF/ customTags.tld</taglib-location>
</taglib>
5、 导入和使用标签库:
现在在JSP页面中就可以导入和使用标签了,语法如下:
//导入标签库
<%@ taglib uri="/ customTags " prefix="custTag" %>
//引用标签
< custTag: tagname />或< custTag: tagname>------< custTag: tagname/>
JSP页面定义的标签元素是如何在WEB容器中找到对应的标签处理器的呢?从定制标签的步骤,我们不难绘出定制标签映射图(如图六所示),可以清晰看出在WEB容器中定制标签元素是如何找到相应的标签处理器的。图六清晰地放映了定制标签的运行机制。
五、 如何在TOMCAT上发布
将编写好的标签处理器CLASS文件、标签库描述文件、WEB.xml文件和WEB应用程序打包成WEAR组件,就可以发布到TOMCAT等WEB容器上。经解压文件目录类似如图七结构,
其中customTags.tld为客户定制标签库描述文件,标签处理器类文件位于classes文件夹或包含标签处理器的JAR文件,WEB.XML将customTags.tld映射到WEB应用程序。JSP文件加中存放引用定制标签的JSP页面文件。
六、 典型定制标签的范例
在讲解了开发定制标签的基本原理、方法和步骤后,下面让我们通过一个完整的典型的例子来看在实际应用中如何使用定制标签来封装常见模块,以增强代码的可读性、可维护性、可复用性,提供编码效率。一般的WEB站点都有大量的新闻内容显示和民意调查内容等重用性很高的功能模块,如新浪、搜狐等。下面我们看如何用上面介绍的方法来开发新闻标签。
1、 编写标签处理器类文件
新闻列表标签(用于显示新闻条目)
public class NewsListTag extends TagSupport {
//属性
//对应的SETTER、GETTER方法
public int doStartTag() throws JspException {
//处理从数据库中检索获得的新闻条目集合和新闻显示格式
//输出标签体内容
try {
pageContext.getOut().print(sbOut.toString());
} catch (IOException e) {
throw new JspTagException("NewsListTag::IO Error: " + e.getMessage());
}
return SKIP_BODY ;
}
private ResultSet getRS() throws SQLException,IOException {
//从数据库中检索新闻条目,并返回结果集
return rs;
}
}
新闻内容标签(用于按指定的格式显示某条新闻的具体内容)
public class NewsContentTag extends TagSupport {
//新闻条目的ID号属性
//对应的SETTER、GETTER方法
public int doStartTag() throws JspException {
//从数据库中获得某条新闻的具体内容
//定制新闻显示的格式
//输出新闻内容。
try {
pageContext.getOut().print(sbOut.toString());
} catch (IOException e) {
throw new JspTagException("NewsListTag::IO Error: " + e.getMessage());
}
return SKIP_BODY ;
}
private ResultSet getRS() throws SQLException,IOException {
//按新闻ID号从数据库中获得新闻的具体内容,并返回结果集
return rs;
}
}
2、 编写标签库描述文件TLD(CustomTags.tld)
//标头信息
//标签库信息
<tag>
<name>newsList</name>
<tag-class>NewsListTag</tag-class>
//标签属性集
</tag>
<tag>
<name>newsContent</name>
<tag-class> NewsContentTag</tag-class>
//标签属性集
</tag>
3、 部署标签库
将CustomTags.tld文件放在WEAR包中的WEB-INFO目录下。部署结果类似如图七。
4、 向WEB应用程序注册标签库
在WEB.XML文件中增加如下语句:
<taglib>
<taglib-uri>/ customTags </taglib-uri>
<taglib-location>/WEB-INF/ customTags.tld</taglib-location>
</taglib>
5、 导入和使用标签
下面就可以在JSP文件中导入定制的标签库和定制的标签了,语法如下:
<%@ taglib uri="/ customTags " prefix=" customTags " %>//导入标签库
< customTags: newsList attribute----- />//引用新闻列表标签
< customTags: newsContent attribute----- />//引用新闻内容标签
6、 运行效果
启动TOMCAT,在浏览器中输入相应的URL地址就可以看到类似新浪站点上的新闻条目页面,可以查看按一定内格式输出新闻条目。当想查看某条新闻的具体内容时,点击该条新闻,就在新的页面按定义的格式显示该条新闻的具体内容。运行步骤如下:
1 启动TOMCAT,在地址栏中http://localhost:8080/tagexample/news/news.jsp, 以看到新闻条目界面,浏览新闻标题.,效果如图八.
2 点击新闻条目(新闻标题),可以浏览相应的新闻内容,效果如图九.
文章来源于领测软件测试网 https://www.ltesting.net/