• 深入分析JavaWeb Item23 -- jsp自己定义标签开发入门


    一、自己定义标签的作用

      自己定义标签主要用于移除Jsp页面中的java代码。

    二、自己定义标签开发和使用

    2.1、自己定义标签开发步骤

       1、编写一个实现Tag接口的Java类(标签处理器类)

    要编写一个自己定义标签,首先要实现一个Tag接口的类。可是Jsp内部已经有实现该接口的类,我们先自己实现一个。

    package me.gacl.web.tag;
    
    import java.io.IOException;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.PageContext;
    import javax.servlet.jsp.tagext.Tag;
    
    public class ViewIPTag implements Tag {
    
        //接收传递进来的PageContext对象
        private PageContext pageContext;
    
        @Override
        public int doEndTag() throws JspException {
            System.out.println("调用doEndTag()方法");
            return 0;
        }
    
        @Override
        public int doStartTag() throws JspException {
            System.out.println("调用doStartTag()方法");
            HttpServletRequest request =(HttpServletRequest) pageContext.getRequest();
            JspWriter out = pageContext.getOut();
            String ip = request.getRemoteAddr();
            try {
                //这里输出的时候会抛出IOException异常
                out.write(ip);
            } catch (IOException e) {
                //捕获IOException异常后继续抛出
                throw new RuntimeException(e);
            }
            return 0;
        }
    
        @Override
        public Tag getParent() {
            return null;
        }
    
        @Override
        public void release() {
            System.out.println("调用release()方法");
        }
    
        @Override
        public void setPageContext(PageContext pageContext) {
            System.out.println("setPageContext(PageContext pageContext)");
            this.pageContext = pageContext;
        }
    
        @Override
        public void setParent(Tag arg0) {
    
        }
    
    }

      2、在WEB-INF/文件夹下新建tld文件,在tld文件里对标签处理器类进行描写叙述

      这里写图片描写叙述

      这里的标签描写叙述能够抄写tomcatserverexample里的样例。抄头抄屁股就能够了。

    gacl.tld文件的代码例如以下:

    <?

    xml version="1.0" encoding="UTF-8" ?

    > <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <!-- description用来加入对taglib(标签库)的描写叙述 --> <description>孤傲苍狼开发的自己定义标签库</description> <!--taglib(标签库)的版本号号 --> <tlib-version>1.0</tlib-version> <short-name>GaclTagLibrary</short-name> <!-- 为自己定义标签库设置一个uri。uri以/开头,/后面的内容随便写,如这里的/gacl , 在Jsp页面中引用标签库时,须要通过uri找到标签库 在Jsp页面中就要这样引入标签库:<%@taglib uri="/gacl" prefix="gacl"%> --> <uri>/gacl</uri> <!--一个taglib(标签库)中包括多个自己定义标签。每个自己定义标签使用一个tag标记来描写叙述 --> <!-- 一个tag标记相应一个自己定义标签 --> <tag> <description>这个标签的作用是用来输出client的IP地址</description> <!-- 为标签处理器类配一个标签名。在Jsp页面中使用标签时是通过标签名来找到要调用的标签处理器类的 通过viewIP就能找到相应的me.gacl.web.tag.ViewIPTag类 --> <name>viewIP</name> <!-- 标签相应的处理器类--> <tag-class>me.gacl.web.tag.ViewIPTag</tag-class> <body-content>empty</body-content> </tag> </taglib>

    2.2、在Jsp页面中使用自己定义标签

      1、使用”<%@taglib uri=”标签库的uri” prefix=”标签的使用前缀”%>”指令引入要使用的标签库。

    比如:在jspTag_Test1.jsp中引用gacl标签库

    <%@ page language="java" pageEncoding="UTF-8"%>
    <!-- 使用taglib指令引用gacl标签库,标签库的前缀(prefix)能够随便设置,如这里设置成 prefix="xdp" -->
    <%@taglib uri="/gacl"  prefix="xdp"%>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>输出client的IP</title>
      </head>
    
      <body>
        你的IP地址是(使用java代码获取输出):
        <%
            //在jsp页面中使用java代码获取clientIP地址
            String ip = request.getRemoteAddr();
            out.write(ip);
        %>
        <hr/>
         你的IP地址是(使用自己定义标签获取输出):
         <%--使用自己定义标签viewIP --%>
         <xdp:viewIP/>
      </body>
    </html>

      标签的运行效果例如以下:

      这里写图片描写叙述

      从运行效果种能够看到,使用自己定义标签就能够将jsp页面上的java代码移除掉,如须要在jsp页面上输出client的IP地址时。使用 <xdp:viewIP/>标签就能够取代jsp页面上的这些代码:

     <%
             //在jsp页面中使用java代码获取clientIP地址
             String ip = request.getRemoteAddr();
             out.write(ip);
     %>

      这就是开发和使用自己定义标签的优点。能够让我们的Jsp页面上不嵌套java代码。

    三、自己定义标签的运行流程

      JSP引擎遇到自己定义标签时。首先创建标签处理器类的实例对象。然后依照JSP规范定义的通信规则依次调用它的方法。
      
    1、public void setPageContext(PageContext pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后能够通过这个pageContext对象与JSP页面进行通信。

    2、public void setParent(Tag t)。setPageContext方法运行完后。WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,假设当前标签没有父标签。则传递给setParent方法的參数值为null。

    3、public int doStartTag()。调用了setPageContext方法和setParent方法之后,WEB容器运行到自己定义标签的開始标记时,就会调用标签处理器的doStartTag方法。

    4、public int doEndTag(),WEB容器运行完自己定义标签的标签体后,就会接着去运行自己定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。

    5、public void release(),通常WEB容器运行完自己定义标签后。标签处理器会驻留在内存中,为其他请求server。直至停止web应用时,web容器才会调用release方法。

    调用图例如以下所看到的

    这里写图片描写叙述
    这里写图片描写叙述

    我们在tomcatserver的"workCatalinalocalhostJavaWeb_JspTag_study_20140816orgapachejsp“文件夹下能够找到将jspTag_Test1.jsp翻译成Servlet后的java源码,例如以下图所看到的:

    这里写图片描写叙述

      打开jspTag_005fTest1_jsp.java文件,能够看到setPageContext(PageContext pc)、setParent(Tag t)、doStartTag()、doEndTag()、release()这5个方法的调用顺序和过程。

      jspTag_005fTest1_jsp.java的代码例如以下:

          out.write("    你的IP地址是(使用java代码获取输出):
    ");
          out.write("    ");
    
            //在jsp页面中使用java代码获取clientIP地址
            String ip = request.getRemoteAddr();
            out.write(ip);
    
          out.write("
    ");
          out.write("    <hr/>
    ");
          out.write("     你的IP地址是(使用自己定义标签获取输出):");
          if (_jspx_meth_xdp_005fviewIP_005f0(_jspx_page_context))
            return;
          out.write("
    ");
          out.write("  </body>
    ");
          out.write("</html>
    ");
        } catch (Throwable t) {
          if (!(t instanceof SkipPageException)){
            out = _jspx_out;
            if (out != null && out.getBufferSize() != 0)
              try { out.clearBuffer(); } catch (java.io.IOException e) {}
            if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
          }
        } finally {
          _jspxFactory.releasePageContext(_jspx_page_context);
        }
      }
    
      private boolean _jspx_meth_xdp_005fviewIP_005f0(PageContext _jspx_page_context)
              throws Throwable {
        PageContext pageContext = _jspx_page_context;
        JspWriter out = _jspx_page_context.getOut();
        //  xdp:viewIP
        me.gacl.web.tag.ViewIPTag _jspx_th_xdp_005fviewIP_005f0 = (me.gacl.web.tag.ViewIPTag) _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.get(me.gacl.web.tag.ViewIPTag.class);
        _jspx_th_xdp_005fviewIP_005f0.setPageContext(_jspx_page_context);
        _jspx_th_xdp_005fviewIP_005f0.setParent(null);
        int _jspx_eval_xdp_005fviewIP_005f0 = _jspx_th_xdp_005fviewIP_005f0.doStartTag();
        if (_jspx_th_xdp_005fviewIP_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
          _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.reuse(_jspx_th_xdp_005fviewIP_005f0);
          return true;
        }
        _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.reuse(_jspx_th_xdp_005fviewIP_005f0);
        return false;
      }
    }

      以下重点分析一下 private boolean _jspx_meth_xdp_005fviewIP_005f0(PageContext _jspx_page_context)方法中的代码

      ①、这里是实例化一个viewIP标签处理器类me.gacl.web.tag.ViewIPTag的对象

    //  xdp:viewIP
         me.gacl.web.tag.ViewIPTag _jspx_th_xdp_005fviewIP_005f0 = (me.gacl.web.tag.ViewIPTag) _005fjspx_005ftagPool_005fxdp_005fviewIP_005fnobody.get(me.gacl.web.tag.ViewIPTag.class);

      ②、实例化标签处理器后。调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器

    _jspx_th_xdp_005fviewIP_005f0.setPageContext(_jspx_page_context);

      ③、setPageContext方法运行完后。接着调用的setParent方法将当前标签的父标签传递给当前标签处理器。假设当前标签没有父标签,则传递给setParent方法的參数值为null

     _jspx_th_xdp_005fviewIP_005f0.setParent(null);

      ④、调用了setPageContext方法和setParent方法之后,WEB容器运行到自己定义标签的開始标记时,就会调用标签处理器的doStartTag方法

     int _jspx_eval_xdp_005fviewIP_005f0 = _jspx_th_xdp_005fviewIP_005f0.doStartTag();

      ⑤、WEB容器运行完自己定义标签的标签体后,就会接着去运行自己定义标签的结束标记,此时。WEB容器会去调用标签处理器的doEndTag方法

     if (_jspx_th_xdp_005fviewIP_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)

      这就是自己定义标签的运行流程。

      这里以一个入门级的案例来解说javaweb的自己定义标签开发。

    四、自己定义标签技术的API

    4.1、标签技术的API类继承关系

      这里写图片描写叙述

    五、标签API简介

    5.1、JspTag接口

      JspTag接口是全部自己定义标签的父接口,它是JSP2.0中新定义的一个标记接口。没有不论什么属性和方法。JspTag接口有Tag和SimpleTag两个直接子接口,JSP2.0曾经的版本号中仅仅有Tag接口,所以把实现Tag接口的自己定义标签也叫做传统标签,把实现SimpleTag接口的自己定义标签叫做简单标签。

    5.2、Tag接口

      Tag接口是全部传统标签的父接口。当中定义了两个重要方法(doStartTag、doEndTag)方法和四个常量(EVAL_BODY_INCLUDESKIP_BODYEVAL_PAGESKIP_PAGE),这两个方法和四个常量的作用例如以下:

      (1)WEB容器在解释运行JSP页面的过程中。遇到自己定义标签的開始标记就会去调用标签处理器的doStartTag方法,doStartTag方法运行完后能够向WEB容器返回常量EVAL_BODY_INCLUDESKIP_BODY。假设doStartTag方法返回EVAL_BODY_INCLUDE,WEB容器就会接着运行自己定义标签的标签体;假设doStartTag方法返回SKIP_BODY,WEB容器就会忽略自己定义标签的标签体,直接解释运行自己定义标签的结束标记。

      (2)WEB容器解释运行到自己定义标签的结束标记时,就会调用标签处理器的doEndTag方法,doEndTag方法运行完后能够向WEB容器返回常量EVAL_PAGESKIP_PAGE

    假设doEndTag方法返回常量EVAL_PAGE。WEB容器就会接着运行JSP页面中位于结束标记后面的JSP代码。假设doEndTag方法返回SKIP_PAGE,WEB容器就会忽略JSP页面中位于结束标记后面的全部内容。

      从doStartTag和doEndTag方法的作用和返回值的作用能够看出。开发自己定义标签时能够在doStartTag方法和doEndTag方法体内编写合适的Java程序代码来实现详细的功能。通过控制doStartTag方法和doEndTag方法的返回值,还能够告诉WEB容器是否运行自己定义标签中的标签体内容和JSP页面中位于自己定义标签的结束标记后面的内容。

    5.3、IterationTag接口

      IterationTag接口继承了Tag接口。并在Tag接口的基础上添加了一个doAfterBody方法和一个EVAL_BODY_AGAIN常量。实现IterationTag接口的标签除了能够完毕Tag接口所能完毕的功能外,还能够通知WEB容器是否反复运行标签体内容。对于实现了IterationTag接口的自己定义标签,WEB容器在运行完自己定义标签的标签体后,将调用标签处理器的doAfterBody方法,doAfterBody方法能够向WEB容器返回常量EVAL_BODY_AGAINSKIP_BODY。假设doAfterBody方法返回EVAL_BODY_AGAIN,WEB容器就会把标签体内容再反复运行一次,运行完后接着再调用doAfterBody方法,如此往复,直到doAfterBody方法返回常量SKIP_BODY,WEB容器才会開始处理标签的结束标记和调用doEndTag方法。

      可见,开发自己定义标签时。能够通过控制doAfterBody方法的返回值来告诉WEB容器是否反复运行标签体内容。从而达到循环处理标签体内容的效果。比如,能够通过一个实现IterationTag接口的标签来迭代输出一个集合中的全部元素,在标签体部分指定元素的输出格式。

      在JSP API中也提供了IterationTag接口的默认实现类TagSupport,我们在编写自己定义标签的标签处理器类时,能够继承和扩展TagSupport类,这相比实现IterationTag接口将简化开发工作。

    5.4、BodyTag接口

      BodyTag接口继承了IterationTag接口。并在IterationTag接口的基础上添加了两个方法(setBodyContent、doInitBody)和一个EVAL_BODY_BUFFERED常量。实现BodyTag接口的标签除了能够完毕IterationTag接口所能完毕的功能。还能够对标签体内容进行改动。对于实现了BodyTag接口的自己定义标签,标签处理器的doStartTag方法不仅能够返回前面解说的常量EVAL_BODY_INCLUDE或SKIP_BODY,还能够返回常量EVAL_BODY_BUFFERED

    假设doStartTag方法返回EVAL_BODY_BUFFERED。WEB容器就会创建一个专用于捕获标签体运行结果的BodyContent对象,然后调用标签处理器的setBodyContent方法将BodyContent对象的引用传递给标签处理器。WEB容器接着将标签体的运行结果写入到BodyContent对象中。在标签处理器的兴许事件方法中,能够通过先前保存的BodyContent对象的引用来获取标签体的运行结果,然后调用BodyContent对象特有的方法对BodyContent对象中的内容(即标签体的运行结果)进行改动和控制其输出。

      在JSP API中也提供了BodyTag接口的实现类BodyTagSupport,我们在编写能够改动标签体内容的自己定义标签的标签处理器类时,能够继承和扩展BodyTagSupport类。这相比实现BodyTag接口将简化开发工作。

    5.5、 SimpleTag接口

      SimpleTag接口是JSP2.0中新增的一个标签接口。因为传统标签使用三个标签接口来完毕不同的功能,显得过于繁琐,不利于标签技术的推广,因此。SUN公司为减少标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口。SimpleTag接口与传统标签接口最大的差别在于。SimpleTag接口仅仅定义了一个用于处理标签逻辑的doTag方法,该方法在WEB容器运行自己定义标签时调用。而且仅仅被调用一次。那些使用传统标签接口所完毕的功能,比如是否运行标签体、迭代标签体、对标签体内容进行改动等功能都能够在doTag方法中完毕。

      在JSP API中也提供了SimpleTag接口的实现类SimpleTagSupport。我们在编写简单标签时。能够继承和扩展SimpleTagSupport类,这相比实现SimpleTag接口将简化开发工作。

    5.6、传统标签接口中的各个方法能够返回的返回值说明

      下图列举了Tag接口、IterationTag接口和BodyTag接口中的主要方法及它们分别能够返回的返回值的说明。

      这里写图片描写叙述

    六、开发传统标签实现页面逻辑

      开发者在编写Jsp页面时,常常还须要在页面中引入一些逻辑。比如:

    • 控制jsp页面某一部分内容是否运行。
    • 控制整个jsp页面是否运行。

    • 控制jsp页面内容反复运行。
    • 改动jsp页面内容输出。

        自己定义标签除了能够移除jsp页面java代码外,它也能够实现以上功能。

    6.1、控制jsp页面某一部分内容是否运行  

      编写一个类实现tag接口,控制doStartTag()方法的返回值,假设这种方法返回EVAL_BODY_INCLUDE,则运行标签体,假设返回SKIP_BODY,则不运行标签体。

      SUN公司针对tag接口提供了一个默认的实现类TagSupport,TagSupport类中实现了tag接口的全部方法,因此我们能够编写一个类继承TagSupport类,然后再重写doStartTag方法。

    演示样例代码例如以下:

    TagDemo1.java

    package me.gacl.web.tag;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.Tag;
    import javax.servlet.jsp.tagext.TagSupport;
    
    /**
     * @author gacl
     * TagSupport类实现了Tag接口。TagDemo1继承TagSupport类
     * 
     */
    public class TagDemo1 extends TagSupport {
    
        /* 重写doStartTag方法,控制标签体是否运行
         * @see javax.servlet.jsp.tagext.TagSupport#doStartTag()
         */
        @Override
        public int doStartTag() throws JspException {
            //假设这种方法返回EVAL_BODY_INCLUDE,则运行标签体,假设返回SKIP_BODY,则不运行标签体
            //return Tag.EVAL_BODY_INCLUDE;
            return Tag.SKIP_BODY;
        }
    }

      在WEB-INF文件夹下的tld文件里加入对该标签处理类的描写叙述,例如以下:

     <tag>
             <name>demo1</name>
             <tag-class>me.gacl.web.tag.TagDemo1</tag-class>
             <!--demo1标签有标签体,所以这里的body-content设置为JSP-->
             <body-content>JSP</body-content>
     </tag>

      在jsp页面中导入并使用自己定义标签。例如以下:

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%--在jsp页面中导入自己定义标签库 --%>
    <%@taglib uri="/gacl" prefix="gacl" %>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>控制标签体是否运行</title>
      </head>
    
      <body>
      <%--在jsp页面中使用自己定义标签 demo1标签是带有标签体的。标签体的内容是"孤傲苍狼"这几个字符串--%>
        <gacl:demo1>
            孤傲苍狼
        </gacl:demo1>
      </body>
    </html>

      运行效果例如以下:

    这里写图片描写叙述

    6.2、控制整个jsp页面是否运行

      编写一个类实现tag接口,控制doEndTag()方法的返回值。假设这种方法返回EVAL_PAGE,则运行标签余下的jsp页面,假设返回SKIP_PAGE,则不运行余下的jsp。

    演示样例代码例如以下:

    TagDemo2.java

    package me.gacl.web.tag;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.Tag;
    import javax.servlet.jsp.tagext.TagSupport;
    
    /**
     * @author gacl
     * TagSupport类实现了Tag接口,TagDemo2继承TagSupport类
     */
    public class TagDemo2 extends TagSupport{
    
        /* 重写doEndTag方法,控制jsp页面是否运行
         * @see javax.servlet.jsp.tagext.TagSupport#doEndTag()
         */
        @Override
        public int doEndTag() throws JspException {
            //假设这种方法返回EVAL_PAGE,则运行标签余下的jsp页面,假设返回SKIP_PAGE,则不运行余下的jsp
            return Tag.SKIP_PAGE;
            //return Tag.EVAL_PAGE;
        }
    
    
    }

      在WEB-INF文件夹下的tld文件里加入对该标签处理类的描写叙述,例如以下:

     <tag>
             <name>demo2</name>
             <tag-class>me.gacl.web.tag.TagDemo2</tag-class>
             <!--demo2标签没有标签体,所以这里的body-content设置为empty-->
             <body-content>empty</body-content>
     </tag>

      在jsp页面中导入并使用自己定义标签,例如以下:

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%--在jsp页面中导入自己定义标签库 --%>
    <%@taglib uri="/gacl" prefix="gacl" %>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>控制jsp页面是否运行</title>
      </head>
    
      <body>
             <h1>jsp页面的内容1</h1>
             <%--在jsp页面中使用自己定义标签 demo2标签是不带标签体的--%>
             <gacl:demo2/>
             <h1>jsp页面的内容2</h1>
      </body>
    </html>

      运行效果例如以下:

     这里写图片描写叙述

    6.3、控制jsp页面内容反复运行

      编写一个类实现Iterationtag接口,控制doAfterBody()方法的返回值。假设这种方法返回EVAL_BODY_AGAIN。 则webserver又运行一次标签体。依次类推,一直运行到doAfterBody方法返回SKIP_BODY。则标签体才不会反复运行。

    演示样例代码例如以下:

    TagDemo3.java

    package me.gacl.web.tag;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.IterationTag;
    import javax.servlet.jsp.tagext.Tag;
    import javax.servlet.jsp.tagext.TagSupport;
    
    public class TagDemo3 extends TagSupport {
    
        int x = 5;
        @Override
        public int doStartTag() throws JspException {
            return Tag.EVAL_BODY_INCLUDE;
        }
    
        /* 控制doAfterBody()方法的返回值,
         * 假设这种方法返回EVAL_BODY_AGAIN, 则webserver又运行一次标签体,
         * 依次类推,一直运行到doAfterBody方法返回SKIP_BODY,则标签体才不会反复运行。
         * @see javax.servlet.jsp.tagext.TagSupport#doAfterBody()
         */
        @Override
        public int doAfterBody() throws JspException {
            x--;
            if(x>0){
                return IterationTag.EVAL_BODY_AGAIN;
            }else{
                return IterationTag.SKIP_BODY;
            }
        }
    
    }

      在WEB-INF文件夹下的tld文件里加入对该标签处理类的描写叙述,例如以下:

     <tag>
             <name>demo3</name>
             <tag-class>me.gacl.web.tag.TagDemo3</tag-class>
             <!--demo3标签有标签体,所以这里的body-content设置为JSP-->
             <body-content>JSP</body-content>
     </tag>

      在jsp页面中导入并使用自己定义标签,例如以下:

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%--在jsp页面中导入自己定义标签库 --%>
    <%@taglib uri="/gacl" prefix="gacl" %>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>控制页面内容反复运行5次</title>
      </head>
    
      <body>
      <%--在jsp页面中使用自己定义标签 demo3标签--%>
          <gacl:demo3>
              <h3>jsp页面的内容</h3>
          </gacl:demo3>
      </body>
    </html>

      运行效果例如以下:

      这里写图片描写叙述

    6.4、改动jsp页面内容输出

      编写一个类实现BodyTag接口,控制doStartTag()方法返回EVAL_BODY_BUFFERED,则webserver会创建BodyContent对象捕获标签体,然后在doEndTag()方法体内,得到代表标签体的bodyContent对象,从而就能够对标签体进行改动操作。

      SUN公司针对BodyTag接口提供了一个默认的实现类BodyTagSupport。BodyTagSupport类中实现了BodyTag接口的全部方法。因此我们能够编写一个类继承BodyTagSupport类,然后再依据须要重写doStartTag方法和doEndTag()方法。

    演示样例代码例如以下:

    TagDemo4.java

    package me.gacl.web.tag;
    
    import java.io.IOException;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.BodyContent;
    import javax.servlet.jsp.tagext.BodyTag;
    import javax.servlet.jsp.tagext.BodyTagSupport;
    import javax.servlet.jsp.tagext.Tag;
    
    /**
     * @author gacl
     * BodyTagSupport类实现了BodyTag接口接口,TagDemo4继承 BodyTagSupport类
     */
    public class TagDemo4 extends BodyTagSupport {
    
        /* 控制doStartTag()方法返回EVAL_BODY_BUFFERED
         * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
         */
        @Override
        public int doStartTag() throws JspException {
            return BodyTag.EVAL_BODY_BUFFERED;
        }
    
        @Override
        public int doEndTag() throws JspException {
    
            //this.getBodyContent()得到代表标签体的bodyContent对象
            BodyContent bodyContent = this.getBodyContent();
            //拿到标签体
            String content = bodyContent.getString();
            //改动标签体里面的内容,将标签体的内容转换成大写
            String result = content.toUpperCase();
            try {
                //输出改动后的内容
                this.pageContext.getOut().write(result);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    
            return Tag.EVAL_PAGE;
        }
    }

      在WEB-INF文件夹下的tld文件里加入对该标签处理类的描写叙述,例如以下:

     <tag>
             <name>demo4</name>
             <tag-class>me.gacl.web.tag.TagDemo4</tag-class>
             <!--demo4标签有标签体,所以这里的body-content设置为JSP-->
             <body-content>JSP</body-content>
     </tag>

      在jsp页面中导入并使用自己定义标签,例如以下:

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%--在jsp页面中导入自己定义标签库 --%>
    <%@taglib uri="/gacl" prefix="gacl" %>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>改动jsp页面内容输出</title>
      </head>
    
      <body>
      <%--在jsp页面中使用自己定义标签 demo4标签--%>
          <gacl:demo4>
              <h3>xdp_gacl</h3>
          </gacl:demo4>
      </body>
    </html>

      运行效果例如以下:

      这里写图片描写叙述

    七、jsp传统标签开发总结

      在如今的jsp标签开发中,非常少直接使用传统标签来开发了,眼下用得较多的都是简单标签。所以Jsp的传统标签开发了解一下就可以,下一篇重点介绍jsp简单标签的开发

  • 相关阅读:
    使用 RestTemplateBuilder.build() 代替 new RestTemplate()
    R2DBC加入Reactive基金会
    Spring Data 2020.0.1 发布
    前后端分离,注册和登录。涉及Oauth2 Password-Flow 授权方式
    OAuth2 Google、Github自定义登录页面
    Authorization-Server入门(二)
    Authorization-Server入门(一)
    Google或Github 登录Web应用​
    使用SpringBoot发送Gmail和QQ邮箱
    理解同步/异步和阻塞/非阻塞的区别
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7054005.html
Copyright © 2020-2023  润新知