JSP 与XML 联合开发技

本文介绍了JSP程序中如何使用taglib编译指令导入和使用自定义标记库,包括taglib指令的语法、标记库的验证方法以及JSP程序的执行流程。在JSP的运行过程中,涉及了parsing、validation、translation和execution四个步骤。通过示例代码,阐述了tag库和tag的工作原理,以及如何开发和测试自定义tag库。

JSP 与XML 联合开发技
 
jsp高级编程252页

taglib 编译指令
在JSP 程序中我们可以通过taglib 编译指令在J 中导入Tag Libraries 关于taglib 操
作指令的知识我们在本系列第一本书中已经提到过为了本书的结构完整起见我们把
这部分的内容复述如下供读者参考
JSP 程序可用的标记/指令集可以通过使用标记库(Tag Library)的形式来进一步扩充
在JSP 程序中用taglib 编译指令声明该程序中可以使用的标记库用URI 参数唯一地标
识这个标记库并指定一个相应的标记库识别符(prefix)用来辨别不同标记库标记的使用
如果一个JSP 编译器不能定位一个标记库(即在URI 位置处没有找到相应的标记库) 那么
会引发一个致命的编译错误如果在taglib 指令之前使用了它所引入的标记库识别符也
会引发致命的编译错误
标记库可以包含一个确认方法(Validation Method) 用这个方法可以确定JSP 页面是否
正确使用了该标记库的功能taglib 指令的语法形式如下所示
<%@ taglib uri="tagLibraryURI" prefix="tagPrefix" %>
其中的属性含义是
 uri 唯一的指定标记库的绝对URI 或相对URI URI 用于定位这个标记库的位置
 tagPrefix 指定所用的标记库的识别符定义了<prefix:tagname>标记中的prefix
用以区别用户所使用的不同的标记库

<leaPrefix:myTag>
注意jsp jspx java servlet sun 和sunw 等是保留的标记库识别符用户不能定
义这样的识别符在目前的规范里空识别符是不允许的
下面的JSP 代码片断演示了在JSP 程序中如何使用自定义的标记库

<%@ taglib uri="leaApp/mytags" prefix="leaTags" />
...
<leaTags:playPingPong>
...
</leaTags:playPingPong>
在上面的代码中taglib 编译指令引入了一个自定义标记库该标记库的相对地址(URI)
为leaApp/mytags 该标记库的识别符是leaTags 这个JSP 程序不能够再使用这个识别符以
引入其它的标记库本例中我们假设此标记库中有playPingPong 这个Tag 并在JSP 程序
中使用它
注意如果Java 编译器碰到一个形如tagName 的标记这个标记是由taglib 编译指令
引入的但是tagName 在相应的标记库里不存在那么这也将导致致命的编译
错误假设在上面的例子中leaApp/mytags 标记库里没有定义playPingPong
这个标记那么将发生致命的编译错误
6.2.2 Tag Library 和Tag 的原理
本小节将介绍Tag Library 与Tag 的工作原理这个问题涉及到两大方面第一个方面
是JSP 程序的执行原理第二个方面就是Tag 的执行原理
我们首先介绍第一个方面JSP 程序的运行原理根据JSP1.2 规范的描述JSP 程
序的运行可以分为这样的几个步骤
Parsing
在这一步JSP 引擎将检查JSP 程序的源代码看看是否有违反语法的地方如果有
那么抛出错误信息不运行此JSP 程序如果一切正常那么就把这个JSP 程序翻译为XML
文件的格式也就是把这个JSP 程序按照XML 文件的格式重新写一遍我们在前面已经
提到过JSP 程序有两种书写方式一种方式是普通的HTML 标记加上JSP 指令与Java 脚
本第二种书写方式就是把JSP 指令替换为特定的XML 标记这些标记在一个DTD 文件
中给出了定义所谓的Parsing 过程就是把按第一种方式书写的JSP 程序翻译为以第二种方
式书写的JSP 程序并加上一些debug 信息例如
<%@ include file=”copyright.hmtl” %>
将会被替换为
<jsp:directive.include file=”copyright.html” />
在这一过程中JSP 引擎还会处理include 进来的文件识别那些是由JSP 指令转换过
来的XML 标记那些是程序员自定义的标记实际上我们可以直接以第二种方式书写
JSP 程序这样Parsing 过程会被JSP 引擎忽略掉JSP 程序的运行速度将有所加快的
 
第6 章 JSP 与XML 联合开发技术
Validation
这一步所作的工作就是验证JSP 程序中所使用的自定义标记库检查程序员是否正确
使用了该标记库的功能JSP 引擎会按照所使用的自定义标记库的出现顺序逐个验证它
们查看每一个自定义Tag 是否有对应的TagExtraInfo 类(亦即下文的TEI 类) 如果有
那么就调用相应的TagExtraInfo 类的isValid()方法检查程序员是否正确使用了该标记的属
性与参数
Translation
在这一步中JSP 程序(XML 格式的)被JSP 引擎翻译为一个标准的Java 类该Java
类一般继承了HttpJspPage 接口覆盖了_jspService()方法该类编译执行的结果就是我们
所看到的JSP 程序的执行结果请看程序清单6.1
程序清单6.1(test.jsp)
<%
out.println("你好");
%>
程序清单6.1 经过JSP 引擎翻译后所产生的Java 类文件如下所示(程序清单6.2 有少
量改动主要是代码缩进方面)
程序清单6.2
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Vector;
import org.apache.jasper.runtime.*;
import java.beans.*;
import org.apache.jasper.JasperException;
public class _0002ftest_0002ejsptest_jsp_1 extends HttpJspBase
{
static
{
}
public _0002ftest_0002ejsptest_jsp_1( )
{
}
private static boolean _jspx_inited = false;
 
第二部分 JSP 技术和XML 技术
public final void _jspx_init() throws JasperException
{
}
public void _jspService(HttpServletRequest request HttpServletResponse response)
throws IOException ServletException
{
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
String _value = null;
try
{
if (_jspx_inited == false)
{
_jspx_init();
_jspx_inited = true;
}
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=8859_1");
pageContext = _jspxFactory.getPageContext(this request response
"" true 8192 true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
//begin [file="E://temp//Down//Tomcat3.2//webapps//ROOT//test.jsp";
//from=(0 2);to=(2 0)]
out.println("脛茫潞脙");
// end
}
catch (Exception ex)
{
if (out.getBufferSize() != 0)
out.clearBuffer();
pageContext.handlePageException(ex);
 
第6 章 JSP 与XML 联合开发技术
}
finally
{
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
}
}
注意程序清单6.1/6.2 所使用的JSP 服务器为Tomcat 3.2 操作系统平台为Win Me
JDK 版本为1.3
根据程序清单6.2 我们应该获得这样的信息该Java 类继承自HttpJspPage 接口
HttpJspPage 接口又继承于JspPage 接口JspPage 接口继承于Servlet 接口Servlet 接口继
承于GenericServlet 类可见关于JSP 程序被编译为一个Servlet 类文件的说法还是有一
定道理的Servlet 程序几乎都继承了HttpServelt 类而HttpServlet 类正是继承于
GenericServlet 类所以HttpJspPage 接口和HttpServlet 还是有点血缘关系的在程序清单
6.2 中最重要的方法是_jspService()方法该方法实现了JSP 程序(程序清单6.1 中的JSP
程序)的所有功能把你好输出到客户端
Execution
这一步就是编译上面一步所产生的Java 文件产生class 文件并调用Java 虚拟机执
行它结果首先存放在缓冲区中程序执行完毕再一并输出到客户端
有的读者可能会问JSP 程序的执行流程与Tag 的工作原理又有何关系呢?我们的回答
是有很大的关系请接着往下看我们介绍这个问题的第二个方面Tag 的工作原理
要说Tag 的工作原理首先必须提到Tag 的编写方法Tag/Tag Library 的编写方法如
下所述
首先确立编写的目标
我们首先需要明确都需要实现那些目标需要封装什么功能Tag 的名字是什么初
步设计Tag 的使用方法Tag 是否需要参数这个Tag 都需要那些属性需要用到哪个Java
API 开发平台是什么这些问题我们都需要考虑得十分清楚而且这些问题在考虑清楚以
前不要轻易编写程序
编写TLD 文件
所谓的TLD 文件指的是Tag Library Descriptor Files 中文意义为标记库描述符文件
这是一个XML 格式的文件它描述了Tag Library 的详细信息它的具体作用有以下几个
方面
1 指定此Tag Library 的版本号
2 指定Tag Library 所遵守的JSP 规范的版本号至少是1.1
3 指定此Tag Library 的名字例如Application
 
第二部分 JSP 技术和XML 技术
4 指定此Tag Library 的URI 普通资源定位符
5 指定此Tag Library 的验证类(validator class)
6 指定此Tag Library 的事件监听类(listener)
7 一些注释信息
对于特定的Tag TLD 文件给出了下面的信息
1 指定了Tag 的名字
2 指定了Tag Hander 即真正实现了该Tag 功能的Java 类
3 指定了TEI 类利用该类可以获取Tag 的附加信息也就是获取Tag 的某些
属性值
4 指定了Tag 标记体内的数据类型亦即<Tag>标记与</Tag>标记之间内容的数据
类型
5 一些注释信息
6 指定了Tag 的属性信息
编写Tag Handler
当编写好TLD 文件以后我们就可以针对特定的Tag 编写特定的Tag Handler 了真
正实现Tag 的功能当然了Tag Handler 的编写有一套规则不是随便一个Java 类都可以
作为Tag Handler 的我们在下文还要详细讨论这个问题
打包Tag Library
我们为每一个Tag 都编写好Tag Handler 以后就可以把所有的类文件与TLD 文件打
包到一个jar 文件中然后把它分发部署到JSP 服务器上去这需要对服务器的配置做一点
小小的改动
测试Tag Library
在这一步中我们需要编写一个JSP 程序使用该Tag Library 的Tag 看看是否实现
了原来设计的功能请看下面的程序清单6.3 这是一个Tomcat 3.2 服务器所自带的例子
有少量改动
程序清单6.3(foo.jsp)
<html>
<body>
<%@ taglib uri="http://java.apache.org/tomcat/examples-taglib" prefix="eg" %>
Radio stations that rock:
<ul>
<eg:foo att1="98.5" att2="92.3" att3="107.7">
<li><%= member %></li>
</eg:foo>
</ul>
<eg:log>
Did you see me on the stderr window?
 
第6 章 JSP 与XML 联合开发技术
</eg:log>
<eg:log toBrowser="true">
Did you see me on the browser window as well?
</eg:log>
</body>
</html>
在程序清单6.3 中首先使用taglib 操作指令导入一个Tag Library simple 指定了
该Tag Library 的URI 地址与标识符(prefix=eg) 在下面的代码段中则分别验证了foo 标
记与log 标记的使用foo 标记与log 标记都是属于simple Tag Library 的标记
到此为止一个Tag Library 就算开发成功了我们除了可以自己使用这个Tag Library
也可以把它上载到网络中供别人使用
现在我们可以对Tag 的工作原理进行讨论了我们参考上文所介绍的JSP 程序的执
行流程看看在每一步中都发生了哪些事情
Parsing
在这一过程中如果JSP 程序用到了Tag Library 那么JSP 引擎会读入该Tag Library
的TLD 文档对其进行分析以便把标准的XML 标记(指的是由JSP 指令转化而来的XML
标记)与自定义的Tag 识别开来
Validation
在这一过程中JSP 引擎会根据TLD 文件的描述信息对Tag Library 进行验证工作
如果有某些标记指定了TEI class 那么JSP 引擎会利用这些类的isValid()方法对Tag 的属
性值进行检验
Translation
这一步是十分关键的一步JSP 引擎会根据taglib 编译指令指定的Tag Library 的URI
地址把含有Tag Handler 的jar 文件载入把JSP 文件中使用了Tag(指自定义的Tag)的地
方用Tag Handler 所定义的方法代替例如doStartTag()方法doAfterBody()方法等然后
JSP 引擎再把整个JSP 程序翻译为标准的JSP 扩展类亦即一个Java 类
Execution
在这一步JSP 引擎调用Java 虚拟机对翻译好的JSP 程序文件进行编译运行无论JSP
程序中有没有使用Tag Library 这一步都是一样的没有什么区别
读者都应该明白了吧下面我们讨论一些细节性的问题即应该如何开发一个Tag
Library 并把它应用到JSP 程序的开发中去
注意本章所有开发的例子的开发环境操作系统为Windows Me 中文版JDK 为JDK
1.3 SE JSP 服务器为Tomcat 3.2 服务器安装路径为E:/temp/Down/Tomcat3.2
下文中一律以TOMCATHOME 代替
 
第二部分 JSP 技术和XML 技术
6.2.3 编写TLD
在定好了开发目标以后第一件要做的工作就是开发TLD 文件在上文已经提到过
TLD 文件的作用就是描述Tag Library 和Tags 的详细信息TLD 文件在Tag Library 中的地
位十分重要一个Tag Library 的成败几乎全部取决于TLD 文件的成败而且如果出现错
误多半是因为TLD 文件编写不规范造成的因为我们编写Tag Handler 时必须参照TLD 文
件的定义
TLD 文件本质上是一个XML 文件该文件可以使用的标记在另外的一个DTD 文件中
有定义这个DTD 文件的名字为web-jsptaglibrary_1_1.dtd 读者可以在下面的网址中找到
这个文件
http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd
读者如果熟悉这个DTD 文件对于正确编写一个TLD 文件是十分有好处的下面我
们就把这个DTD 文件列出来并结合具体的TLD 文档解释每个标记的含义并介绍如
何编写一个TLD 文件
程序清单6.4(web-jsptaglibrary_1_1.dtd:有部分删节)
<!--
This is the DTD defining the JavaServer Pages 1.1 Tag Library
descriptor (.tld) (XML) file format/syntax.
A Tag Library is a JAR file containing a valid instance of a Tag Library
Descriptor (taglib.tld) file in the META-INF subdirectory along with the
appropriate implementing classes and other resources required to
implement the tags defined therein.
-->
<!--
The taglib tag is the document root it defines:
tlibversion the version of the tag library implementation
jspversion the version of JSP the tag library depends upon
shortname a simple default short name that could be used by
a JSP authoring tool to create names with a mnemonic
value; for example the it may be used as the prefered
prefix value in taglib directives
uri a uri uniquely identifying this taglib
info a simple string describing the "use" of this taglib
should be user discernable
-->
<!ELEMENT taglib (tlibversion jspversion? shortname uri? info? tag+) >
<!ATTLIST taglib id ID #IMPLIED xmlns CDATA #FIXED
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
Describes this version (number) of the taglibrary (dewey decimal)
#PCDATA ::= [0-9]*{ "."[0-9] }0..3
-->
 
第6 章 JSP 与XML 联合开发技术
<!ELEMENT tlibversion (#PCDATA) >
<!--
Describes the JSP version (number) this taglibrary requires in
order to function (dewey decimal)
The default is 1.1
#PCDATA ::= [0-9]*{ "."[0-9] }0..3
-->
<!ELEMENT jspversion (#PCDATA) >
<!--
Defines a short (default) shortname to be used for tags and
variable names used/created by this tag library. Do not use
white space and do not start with digits or underscore.
#PCDATA ::= NMTOKEN
-->
<!ELEMENT shortname (#PCDATA) >
<!--
Defines a public URI that uniquely identifies this version of
the taglibrary Leave it empty if it does not apply.
-->
<!ELEMENT uri (#PCDATA) >
<!--
Defines an arbitrary text string descirbing the tag library
-->
<!ELEMENT info (#PCDATA) >
<!--
The tag defines a unique tag in this tag library defining:
- the unique tag/element name
- the subclass of javax.servlet.jsp.tagext.Tag implementation class
- an optional subclass of javax.servlet.jsp.tagext.TagExtraInfo
- the body content type (hint)
- optional tag-specific information
- any attributes
-->
<!ELEMENT tag (name tagclass teiclass? bodycontent? info? attribute*) >
<!--
Defines the subclass of javax.serlvet.jsp.tagext.Tag that implements
the request time semantics for this tag. (required)
#PCDATA ::= fully qualified Java class name
-->
<!ELEMENT tagclass (#PCDATA) >
<!--
Defines the subclass of javax.servlet.jsp.tagext.TagExtraInfo for
this tag. (optional)
 
第二部分 JSP 技术和XML 技术
If this is not given the class is not consulted at translation time.
#PCDATA ::= fully qualified Java class name
-->
<!ELEMENT teiclass (#PCDATA) >
<!--
Provides a hint as to the content of the body of this tag. Primarily
intended for use by page composition tools.
There are currently three values specified:
tagdependent The body of the tag is interpreted by the tag
implementation itself and is most likely in a
different "language" e.g embedded SQL statements.
JSP The body of the tag contains nested JSP syntax
empty The body must be empty
The default (if not defined) is JSP
#PCDATA ::= tagdependent | JSP | empty
-->
<!ELEMENT bodycontent (#PCDATA) >
<!--
The attribute tag defines an attribute for the nesting tag
An attribute definition is composed of:
- the attributes name (required)
- if the attribute is required or optional (optional)
- if the attributes value may be dynamically calculated at runtime
by a scriptlet expression (optional)
-->
<!ELEMENT attribute (name required? rtexprvalue?) >
<!--
Defines the canonical name of a tag or attribute being defined
#PCDATA ::= NMTOKEN
-->
<!ELEMENT name (#PCDATA) >
<!--
Defines if the nesting attribute is required or optional.
#PCDATA ::= true | false | yes | no
If not present then the default is "false" i.e the attribute
is optional.
-->
<!ELEMENT required (#PCDATA) >
<!--
Defines if the nesting attribute can have scriptlet expressions as
a value i.e the value of the attribute may be dynamically calculated
at request time as opposed to a static value determined at translation
time.
 
第6 章 JSP 与XML 联合开发技术
#PCDATA ::= true | false | yes | no
If not present then the default is "false" i.e the attribute
has a static value
-->
<!ELEMENT rtexprvalue (#PCDATA) >
<!ATTLIST tlibversion id ID #IMPLIED>
<!ATTLIST jspversion id ID #IMPLIED>
<!ATTLIST shortname id ID #IMPLIED>
<!ATTLIST uri id ID #IMPLIED>
<!ATTLIST info id ID #IMPLIED>
<!ATTLIST tag id ID #IMPLIED>
<!ATTLIST tagclass id ID #IMPLIED>
<!ATTLIST teiclass id ID #IMPLIED>
<!ATTLIST bodycontent id ID #IMPLIED>
<!ATTLIST attribute id ID #IMPLIED>
<!ATTLIST name id ID #IMPLIED>
<!ATTLIST required id ID #IMPLIED>
<!ATTLIST rtexprvalue id ID #IMPLIED>
在程序清单6.4 所列出来的DTD 文件中定义了所有在TLD 文件中可用的XML标记
在这个DTD 文档中有很多英文注释这些注释解释了每个标记的用途看不懂!不要紧
下面我们就来结合一个具体的TLD 文件实例逐个解释这些标记的意义与用途

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值