jsp自定义标签介绍与操作实例

  • 来源: 龙腾软件教程网 作者: 若水   2008-05-09/23:59
  • JSP自定义标签体系结构介绍

    标签处理程序

    在创建自定义标签之前,需要创建一个 标签处理程序。标签处理程序是一个执行自定义标签操作的 Java 对象。在使用自定义标签时,要导入一个 标签库 —— 即一组标签/标签处理程序对。通过在 Web 部署描述符中声明库导入它,然后用指令 taglib 将它导入 JSP 页。
    如果 JSP 容器在转换时遇到了自定义标签,那么它就检查 标签库描述符(tag library descriptor) (TLD) 文件以查询相应的标签处理程序。TLD 文件对于自定义标签处理程序,就像 Web 部署描述符对于 servlet 一样。
    在运行时,JSP 页生成的 servlet 得到对应于这一页面所使用的标签的标签处理程序的一个实例。生成的 servlet 用传递给它的属性初始化标签处理程序。
    标签处理程序实现了生存周期方法。生成的 servlet 用这些方法通知标签处理程序应当启动、停止或者重复自定义标签操作。生成的 servlet 调用这些生存周期方法执行标签的功能。

    标签的类型

    可以定义两种类型的标签:
    javax.servlet.jsp.tagext.Tag
    javax.servlet.jsp.tagext.BodyTag
    对 正文 进行操作 —— 即对在开始和结束标签之间的内容进行操作的 —— 标签必须实现 BodyTag 接口。在这个教程中,我们将称这些标签为 正文标签。我们将不对其正文操作的标签称为 简单标签。简单标签可以实现 Tag 接口,尽管不要求它们这样做。要记住不对其正文操作的标签仍然 有 正文,只不过,它的标签处理程序不能读取这个正文。
     
    jsp自定义标签
    关键词: jsp自定义标签                                          
    定义标签
    要定义标签,需要:
    •  为该标签开发一个tag handler和helper类
    •  在标签库描述符中声明这个标签
    本节描述标签handler和TLD的属性,并解释如何为在前面几节中介绍的标签开发tag handler和库描述符元素。
    标签handler
    标签handler是由Web容器调用的一个对象,用于执行带有自定义标签的JSP页面时对这个标签进行判断。标签handler必须实现Tag或者BodyTag接口。接口可以用于接受现有Java对象并使它成为标签handler。对于新创建的处理器,可以用TagSupport和BodyTagSupport类作为基类。这些类和接口包含在javax.servlet.jsp.tagext包中。
    JSP页面的servlet在对标签处理的不同阶段调用由Tag和BodyTag接口定义的标签handler。遇到自定义标签的开始标签时,JSP页面的servlet调用方法以初始化相应的handler,然后调用handler的doStartTag方法。遇到自定义标签的结束标签时,调用处理器的doEndTag方法。在标签handler需要与标签的正文交互时调用其他方法,见带正文的标签。为了提供标签handler的实现,必须实现在处理标签的不同阶段调用的方法,在表16-1中汇总了这些方法。

    表16-1标签handler方法

    标签handler类型 方法

    简单  doStartTag, doEndTag, release
    属性  doStartTag, doEndTag, set/getAttribute1...N, release
    正文、判断且无交互  doStartTag, doEndTag, release
    正文、迭代判断  doStartTag, doAfterBody, doEndTag, release
    正文、交互  doStartTag, doEndTag, release, doInitBody, doAfterBody, release
    标签handler可以使用一个能让它得以与JSP页面通信的API。到API的入口点是页面上下文对象(javax.servlet.jsp.PageContext),通过它标签handler可以获取JSP页面能够访问的所有其他隐式对象(请求、会话和应用程序)。
    隐式对象可以有与其相关联的命名属性。可以用[set|get]Attribute方法访问这种属性。
    如果标签是嵌入的,标签handler还可以访问与外围标签关联的handler称为parent)。
    一组相关的标签handler类(标签库)一般是打包的且作为JAR文档部署。
    标签库描述符
    标签库描述符(TLD)是一个描述标签库的XML文档。TLD包含有关整个库以及库中包含的每一个标签的信息。Web容器用TLD验证标签,JSP页面开发工具也使用TLD。
    TLD文件名必须有扩展名.tld。TLD文件也储存在WAR文件的WEB-INF目录中或者在WEB-INF的子目录中。
    TLD必须以指定XML的版本和文档类型定义(DTD)的XML文档序言(prolog)开始。
    <?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">
    Tomcat支持版本 1.1和1.2的DTD。不过,本章所讨论的是1.2版本,因为在开发的所有标签库中都应该使用最新的版本。模板库TLDtutorial-template.tld符合版本1.2。Struts库TLD符合版本1.1的DTD,它的元素要少,且其中一些元素使用了稍微不同的名字。
    TLD的根是taglib元素。表16-2中列出了taglib的子元素:
    表16-2 taglib子子元素 
    元素 说明
    tlib-version  标签库的版本
    jsp-version  这个标签库要求的JSP规范版本
    short-name  JSP页面编写工具可以用来创建助记名的可选名字
    uri  唯一标识该标签库的的URI
    display-name  将由工具显示的可选名
    small-icon  将由工具使用的可选小图标
    large-icon  可被工具使用的可选大图标
    description  可选的标签特定信息
    listener  见listener元素
    tag  见tag元素
    listener元素
    标签库可以指定一些事件监听器类(见处理Servlet生命周期事件)。这些监听器在TLD中作为listener元素列出,Web容器将初始化监听器类并以类似在WAR级定义的监听器的方式注册它们。与WAR级监听器不同,这里没有指定标签库监听器注册的顺序。listener元素的唯一子元素是listener-class元素,它必须包含监听类的完全限定名。#p#分页标题#e#
    tag元素
    库中的每一个标签都由给出其名字和其标签handler的类、在由标签创建的脚本变量上的信息以及标签属性上的信息描述。脚本变量信息可以在TLD中直接给出,也可以通过tag extra info类给出(见定义脚本变量的标签)。每一个属性声明包含指明属性是否是必需的、其值是否可以由请求时表达式确定以及属性类型的内容(见属性元素)。
    在tag元素中的TLD中指定标签。在表16-3中出了tag的子元素:
    表16-3 标签子元素
    元素 说明
    name  唯一标签名
    tag-class  标签handler类的完全限定名
    tei-class  javax.servlet.jsp.tagext.TagExtraInfo的可选子类。见提供有关脚本变量的信息。
    body-content  正文内容类型。见body-conten元素和 body-content元素。
    display-name  由工具显示的可选名
    small-icon  可以由工具使用的小图标
    large-icon  可以由工具使用的大图标
    description  可选的标签特定的信息
    variable  可选的脚本变量信息。见提供有关脚本变量的信息。
    attribute  标签属性信息。见Attribute 元素。
    下面几节描述开发在标签类型中介绍的每一种类型的标签所需要的方法和TLD。
    简单标签
    标签handler
    简单标签的handler必须实现Tag接口的doStartTag和doEndTag方法。在遇到开始标签时调用doStartTag方法。因为简单标签没有正文,所以这个方法返回SKIP_BODY。在遇到结束标签时调用doEndTag方法。如果要对页面的其他部分进行判断,则doEndTag方法需要返回EVAL_PAGE,否则,它就返回SKIP_PAGE。
    在第一节讨论的简单标签
    <tt:simple />
    由下列标签handler实现:
    public SimpleTag extends TagSupport {
      public int doStartTag() throws JspException {
        try {       pageContext.getOut().print("Hello.");
        } catch (Exception ex) {
          throw new JspTagException("SimpleTag: " +
            ex.getMessage());     }
        return SKIP_BODY;   }
      public int doEndTag() {
        return EVAL_PAGE;
      }
    }
    body-content元素
    没有正文的标签必须用body-content元素声明它们的正文内容是空的:
    <body-content>empty</body-content>
     自定义标签实验
    一、概述
           JSP中有一块重要的技术:自定义标签(Custom Tag),最近这几天在学习Struts的时候发现Struts中使用了很多自定义标签,如html、bean等。所以我就做了个简单的试验,学习一下这种技术。
           首先介绍一下这种技术吧!
    1.优点:
    取代了JSP中的Java程序,并且可以重复使用,方便不熟悉Java编程的网页设计人员。
    2.开发流程:
    (1)       编写JSP,在JSP中使用自定义标签。
    (2)       在web.xml中指定JSP中使用的标签的.tld(标签库描述文件)文件的位置。
    (3)       .tld文件中指定标签使用的类。
    3. 自定义标签的分类:
    (1)       简单标签:如< mytag:helloworld/>
    (2)       带属性标签:如<imytag:checkinput dbname = “<myBean.getDBName()>”/>
    (3)       带标签体的标签:
    在自定义标签的起始和结束标签之间的部分为标签体(Body)。Body的内容可以是JSP中的标准标签,也可以是HTML、脚本语言或其他的自定义标签。
    <mytag:checkinput dbname = “<myBean.getDBName()>”>
          <mytag:log message=”Table Name”>
    <mytag:checkinput />
    (4)       可以被Script使用的标签:
    定义了id和type属性的标签可以被标签后面的Scriptlet使用。</P< p>
    <mytag:connection id = “oraDB” type = “DataSource” name = “Oracle”>
    <%oraDB.getConnection(); %>
    4.接口及其他
    实际上,自定义标签的处理类实现了Tag Handler对象。JSP技术在javax.servlet.jsp.tagext中提供了多个Tag Handler接口,JSP1.2中定义了Tag、BodyTag、IterationTag接口,在JSP2.0中新增了SimpleTag接口。JSP还提供了上述接口的实现类TagSupport、BodyTagSupport和SimpleTagSupport(SimpleTagSupport只在JSP2.0中才有)。BodyTagSupport实现了BodyTag、Tag和IterationTag接口。
    接口及其方法
    Tag接口
    方法
    SimpleTag
    dotage
    Tag
    doStartTag,doEndTag,release
    IterationTag
    doStartTag,doAfterTag,release
    BodyTag
    doStartTag,doEndTag,release,doInitBody,doAfterBody
    下表引自Sun的JSP在线教程。
    Tag Handler Methods
    Tag Handler Type
    Methods
    Simple
    doStartTag, doEndTag, release
    Attributes
    doStartTag, doEndTag, set/getAttribute1...N, release
    Body, Evaluation and No Interaction
    doStartTag, doEndTag, release
    Body, Iterative Evaluation
    doStartTag, doAfterBody, doEndTag, release
    Body, Interaction
    doStartTag, doEndTag, release, doInitBody, doAfterBody, release</P< p>
    下表中的EVAL是evaluate的缩写,意思是:评价, 估计, 求...的值,在下列的返回值中的意思是执行。
    返回值
    意义
    SKIP_BODY#p#分页标题#e#
    表示不用处理标签体,直接调用doEndTag()方法。
    SKIP_PAGE
    忽略标签后面的JSP内容。
    EVAL_PAGE
    处理标签后,继续处理JSP后面的内容。
    EVAL_BODY_BUFFERED
    表示需要处理标签体。
    EVAL_BODY_INCLUDE
    表示需要处理标签体,但绕过setBodyContent()和doInitBody()方法
    EVAL_BODY_AGAIN
    对标签体循环处理。
    具体用法可以查看其他参考资料。
    Sun的Java教程相关部分:http://java.sun.com/webservices/docs/1.0/tutorial/doc/JSPTags.html
    二、实验
    1.试验介绍
    下面的实验就是基于上述开发流程开发的。
    (1)在JSP中指定taglib的uri:<%@ taglib uri="/helloworld" prefix="mytag" %>。
    (2)在web.xml中配置tag-location:
    <taglib>
                <taglib-uri>/helloworld</taglib-uri>
                <taglib-location>/WEB-INF/helloworld.tld</taglib-location>
           </taglib>
           (3)在tag-location中指定的.tld文件中定义实现标签的处理类:
       <short-name>mytag</short-name>
       <tag>
          <name>helloworld</name></P< p>
      <tag-class>mytag.HelloWorldTag</tag-class>
          <body-content>empty</body-content>
      </tag>
    (4)执行处理类mytag.HelloWorldTag的doStartTag和doEndTag方法,然后将结果输入到JSP中,和JSP中的内容一起输出。实际上自定义标签和JSP中的其他的内容被WebServer一起编译成servlet。
    2. 完成后的试验的目录结构
    应用myjsp放在Tomcat的webapps下。
    myjsp中包含J2EE标准目录结构:WEB-INF和hello.jsp。WEB-INF中包含子目录classes和lib及web.xml,tld文件可以放在WEB-INF下,也可以放在WEB-INF的子目录下。
     
    3.开始实验
    3.1.编写JSP
    < !—hello.jsp的源码 -- >
    <%@ page contentType="text/html; charset=GBK" %>
    <%@ taglib uri="/helloworld" prefix="mytag" %>
    <html>
    <head>
    <title>
    jsp1
    </title>
    </head>
    <body bgcolor="#ffffc0">
    <h1>
    下面显示的是自定义标签中的内容
    </h1>
    <br><br></P< p>
    <mytag:helloworld></mytag:helloworld>
    <br>
     
    </form>
    </body>
    </html>
     
    3.2.编写web.xml
     
    < !—web.xml的源码 -- >
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- edited with XMLSPY v5 rel. 4 U (http://www.xmlspy.com) by Williams (501) -->
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    <taglib>
            <taglib-uri>/helloworld</taglib-uri>
            <taglib-location>/WEB-INF/helloworld.tld</taglib-location>
    </taglib>
    </web-app>
    3.3  编写tld文件
    < !—helloworld.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"></P< p>
    <taglib>
       <tlib-version>1.0</tlib-version>
       <jsp-version>1.2</jsp-version>
       <short-name>mytag</short-name>
       <tag>
           <name>helloworld</name>
           <tag-class>mytag.HelloWorldTag</tag-class>
           <body-content>empty</body-content>
       </tag></P< p>
    </taglib>
    3.4  编写标签实现类
    < !—标签的实现类HelloWorldTag.class的源码 -- >
    package mytag;   
    import java.io.IOException;
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    public class HelloWorldTag extends TagSupport {    
      public HelloWorldTag() {
      }
      public int doStartTag() throws JspTagException{
        return EVAL_BODY_INCLUDE;
      }
      public int doEndTag() throws JspTagException{
        try {
          pageContext.getOut().write("Hello World");
        }
        catch (IOException ex) {
          throw new JspTagException("错误");
        }
        return EVAL_PAGE;
      }
    }
    3.5  执行效果
    部署到Tomcat的WebApps目录下,启动Tomcat,输入:http://localhost:8080/myjsp/hello.jsp#p#分页标题#e#
     
    “Hello World”就是我们定义的标签部分的处理类输出的结果。
    3.6  注意:
    这个试验我做了2天,总是报错,弄得很是灰心,开始时以为tld文件或web.xml文件配置不正确,但怎么也找不到原因。
    今晚我终于找到原因了,是因为.class文件一定要放在classes文件夹中,我放到了lib中。
    .jar或servlet文件要放在lib目录中,而.class要放在classes目录中,如果要放到lib目录中,必须把mytag中的文件打包成.jar文件,然后把mytag.jar放到lib目录中。

    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多