精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● Java>>JAVA编程>>Java与XML>>Java & XML手记(8)--在JSP中应用XML

主题:Java & XML手记(8)--在JSP中应用XML
发信人: zeus_h(i番茄)
整理人: zjxyz(2002-09-08 22:58:02), 站内信件
发信人: javalover (欲下未下风悠扬), 信区: Java
标  题: Java & XML手记(18)
发信站: 北大未名站 (2001年11月18日17:13:08 星期天) , 站内信件

18.在JSP中应用XML(一)
    在本文中,我们将介绍JSP技术与XML技术整合的第二种模式的实现细节,它的核心就是Ta
g Libraries在JSP程序中的使用,那么在JSP程序中如何使用Tag Libraries呢?

(一)taglib编译指令
    在JSP程序中,我们可以通过taglib编译指令在JSP程序中导入Tag Libraries,关于tagli
b操作指令的知识,我们在《XXX》一书中已经提到过,为了本书的结构完整起见,我们把这部分
的内容复述如下,供大家参考。
    JSP程序可用的标记/指令集可以通过使用”标记库”(Tag Library)的形式来进一步扩充
。在JSP程序中,用taglib编译指令声明该JSP程序中可以使用的标记库。用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这个标记,那么将发生编译错误。


19. 在JSP中应用XML(二)
(二)Tag Library和Tag的原理
    本小节将介绍Tag Library与Tag的工作原理,这个问题涉及到两大方面,第一个方面是JS
P程序的执行原理,第二个方面就是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指令转换过来的XM
L标记,那些是程序员自定义的标记。实际上,我们可以直接以第二种方式书写JSP程序,这样P
arsing 过程会被JSP引擎忽略掉,JSP程序的运行速度将有所加快的。

◆Validation
    这一步所作的工作就是验证JSP程序中所使用的自定义标记库,检查程序员是否正确使用
了该标记库的功能。JSP引擎会按照所使用的自定义标记库的出现顺序,逐个验证它们,查看每
一个自定义Tag是否有对应的TagExtraInfo 类(亦即下文的TEI类),如果有,那么就调用相应的
TagExtraInfo类的isValid()方法,检查程序员是否正确使用了该标记的属性与参数。

◆Translation
    在这一步中,JSP程序(XML格式的)被JSP引擎翻译为一个标准的Java类,该Java类一般继承
了HttpJspPage接口,覆盖了_jspService()方法。该类编译执行的结果就是我们所看到的JSP
程序的执行结果。请看下面的例子:

程序清单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;
     public final void _jspx_init() throws JasperException
         {
     }

public void _jspService(HttpServletRequest request, HttpServletResponse  respons
e)
         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);
 }
finally
{
             out.flush();
             _jspxFactory.releasePageContext(pageContext);
         }
     }
}

注意:
    程序清单6.1/6.2所使用的JSP服务器为Tomcat 3.2,操作系统平台为Win Me,JDK版本为1
.3。

    根据程序清单6.2,我们应该获得这样的信息,该Java类继承自HttpJspPage接口,HttpJsp
Page接口又继承于JspPage接口,JspPage接口继承于Servlet接口,Servlet接口继承于Generi
cServlet类,可见,关于JSP程序被编译为一个Servlet类文件的说法还是有一定的道理的。S
ervlet程序几乎都继承了HttpServelt类,而HttpServlet类正是继承于GenericServlet类,所
以HttpJspPage接口和HttpServlet还是有点血缘关系的。在程序清单6.2中,最重要的方法是
_jspService()方法,该方法实现了JSP程序(程序清单6.1中的JSP程序)的所有功能,把”你好
”输出到客户端。

◆Execution
    这一步就是编译上面一步所产生的Java文件,产生class文件,并调用Java虚拟机执行它,
结果首先存放在缓冲区中,程序执行完毕,再一并输出到客户端。


20. 在JSP中应用XML(三)
Tag Library和Tag的原理-2
有人可能会问JSP程序的执行流程与Tag的工作原理又有何关系呢?我的回答是:有很大的关系
,请接着往下看,我们介绍这个问题的第二个方面-------Tag的工作原理。
要说Tag的工作原理,首先必须提到Tag/Tag Library的编写方法。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。
4.指定此Tag Library的URI,普通资源定位符。
6.指定此Tag Library的验证类(validator class)。
6.指定此Tag Library的事件监听类(listener)。
6.一些注释信息。
对于特定的Tag,TLD文件给出了下面的信息。
1.指定了Tag的名字。
2.指定了Tag Hander,即真正实现了该Tag功能的Java类。
3.指定了TEI类,利用该类,可以获取Tag的附加信息,也就是获取Tag的某些属性值。
4.指定了Tag标记体内的数据类型。亦即<Tag>标记与</Tag>标记之间内容的数据类型。
6.一些注释信息。
6.指定了Tag的属性信息。

◆编写Tag Handler
当编写好TLD文件以后,我们就可以针对特定的Tag编写特定的Tag Handler了,真正实现Tag的
功能,当然了,Tag Handler的编写有一套规则,不是随便一个Java类都可以作为Tag Handler的
,我们在下文还要详细讨论这个问题。

◆打包Tag Library
我们为每一个Tag都编写好Tag Handler以后,就可以把所有的类文件与TLD文件打包到一个ja
r文件中。然后把它分发部署到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:

    <eg:foo att1="98.5" att2="92.3" att3="107.7">
  • <%= member %>

  • </eg:foo>

<eg:log>
Did you see me on the stderr window?
</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,指定了该T
ag Library的URI地址与标识符(prefix=eg),在下面的代码段中,则分别验证了foo标记与log
标记的使用,foo标记与log标记都是属于simple Tag Library的标记。
到此为止,一个Tag Library就算开发成功了,我们除了可以自己使用这个Tag Library,也可
以把它上载到网络中,供别人使用。



21. 在JSP中应用XML(四)
Tag Library和Tag的原理-3
现在,我们可以对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 Handle
r所定义的方法代替,例如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代
替。



--
小楼一夜听春雨,深巷明朝卖杏花。

※ 来源:·北大未名站 bbs.pku.edu.cn·[FROM: 162.105.106.162]
--------------------------------------------------------------------------------
.. 返回



----
象我这一种男人,学不懂怎快乐!
       

[关闭][返回]