zoukankan      html  css  js  c++  java
  • javaweb学习总结(二十四)——jsp传统标签开发

    一、标签技术的API

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

      

    二、标签API简单介绍

    2.1、JspTag接口

      JspTag接口是所有自定义标签的父接口,它是JSP2.0中新定义的一个标记接口,没有任何属性和方法。JspTag接口有Tag和SimpleTag两个直接子接口,JSP2.0以前的版本中只有Tag接口,所以把实现Tag接口的自定义标签也叫做传统标签,把实现SimpleTag接口的自定义标签叫做简单标签

    2.2、Tag接口

      Tag接口是所有传统标签的父接口,其中定义了两个重要方法(doStartTag、doEndTag)方法和四个常量(EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE、SKIP_PAGE),这两个方法和四个常量的作用如下:

      (1)WEB容器在解释执行JSP页面的过程中,遇到自定义标签的开始标记就会去调用标签处理器的doStartTag方法,doStartTag方法执行完后可以向WEB容器返回常量EVAL_BODY_INCLUDE或SKIP_BODY。如果doStartTag方法返回EVAL_BODY_INCLUDE,WEB容器就会接着执行自定义标签的标签体;如果doStartTag方法返回SKIP_BODY,WEB容器就会忽略自定义标签的标签体,直接解释执行自定义标签的结束标记。

      (2)WEB容器解释执行到自定义标签的结束标记时,就会调用标签处理器的doEndTag方法,doEndTag方法执行完后可以向WEB容器返回常量EVAL_PAGE或SKIP_PAGE。如果doEndTag方法返回常量EVAL_PAGE,WEB容器就会接着执行JSP页面中位于结束标记后面的JSP代码;如果doEndTag方法返回SKIP_PAGE,WEB容器就会忽略JSP页面中位于结束标记后面的所有内容。

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

    2.3、IterationTag接口

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

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

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

    2.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接口将简化开发工作。

    2.5、 SimpleTag接口

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

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

    2.6、传统标签接口中的各个方法可以返回的返回值说明

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

      

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

      开发人员在编写Jsp页面时,经常还需要在页面中引入一些逻辑,例如:

    • 控制jsp页面某一部分内容是否执行。
    • 控制整个jsp页面是否执行。
    • 控制jsp页面内容重复执行。
    • 修改jsp页面内容输出。

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

    3.1、控制jsp页面某一部分内容是否执行  

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

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

    示例代码如下:

    TagDemo1.java

    复制代码
     1 package me.gacl.web.tag;
     2 
     3 import javax.servlet.jsp.JspException;
     4 import javax.servlet.jsp.tagext.Tag;
     5 import javax.servlet.jsp.tagext.TagSupport;
     6 
     7 /**
     8  * @author gacl
     9  * TagSupport类实现了Tag接口,TagDemo1继承TagSupport类
    10  * 
    11  */
    12 public class TagDemo1 extends TagSupport {
    13 
    14     /* 重写doStartTag方法,控制标签体是否执行
    15      * @see javax.servlet.jsp.tagext.TagSupport#doStartTag()
    16      */
    17     @Override
    18     public int doStartTag() throws JspException {
    19         //如果这个方法返回EVAL_BODY_INCLUDE,则执行标签体,如果返回SKIP_BODY,则不执行标签体
    20         //return Tag.EVAL_BODY_INCLUDE;
    21         return Tag.SKIP_BODY;
    22     }
    23 }
    复制代码

      在WEB-INF目录下的tld文件中添加对该标签处理类的描述,如下:

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

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

    复制代码
     1 <%@ page language="java" pageEncoding="UTF-8"%>
     2 <%--在jsp页面中导入自定义标签库 --%>
     3 <%@taglib uri="/gacl" prefix="gacl" %>
     4 <!DOCTYPE HTML>
     5 <html>
     6   <head>
     7     <title>控制标签体是否执行</title>
     8   </head>
     9   
    10   <body>
    11   <%--在jsp页面中使用自定义标签 demo1标签是带有标签体的,标签体的内容是"孤傲苍狼"这几个字符串--%>
    12     <gacl:demo1>
    13         孤傲苍狼
    14     </gacl:demo1>
    15   </body>
    16 </html>
    复制代码

      运行效果如下:

     

    3.2、控制整个jsp页面是否执行

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

    示例代码如下:

    TagDemo2.java

    复制代码
     1 package me.gacl.web.tag;
     2 
     3 import javax.servlet.jsp.JspException;
     4 import javax.servlet.jsp.tagext.Tag;
     5 import javax.servlet.jsp.tagext.TagSupport;
     6 
     7 /**
     8  * @author gacl
     9  * TagSupport类实现了Tag接口,TagDemo2继承TagSupport类
    10  */
    11 public class TagDemo2 extends TagSupport{
    12 
    13     /* 重写doEndTag方法,控制jsp页面是否执行
    14      * @see javax.servlet.jsp.tagext.TagSupport#doEndTag()
    15      */
    16     @Override
    17     public int doEndTag() throws JspException {
    18         //如果这个方法返回EVAL_PAGE,则执行标签余下的jsp页面,如果返回SKIP_PAGE,则不执行余下的jsp
    19         return Tag.SKIP_PAGE;
    20         //return Tag.EVAL_PAGE;
    21     }
    22 
    23     
    24 }
    复制代码

      在WEB-INF目录下的tld文件中添加对该标签处理类的描述,如下:

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

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

    复制代码
     1 <%@ page language="java" pageEncoding="UTF-8"%>
     2 <%--在jsp页面中导入自定义标签库 --%>
     3 <%@taglib uri="/gacl" prefix="gacl" %>
     4 <!DOCTYPE HTML>
     5 <html>
     6   <head>
     7     <title>控制jsp页面是否执行</title>
     8   </head>
     9   
    10   <body>
    11          <h1>jsp页面的内容1</h1>
    12          <%--在jsp页面中使用自定义标签 demo2标签是不带标签体的--%>
    13          <gacl:demo2/>
    14          <h1>jsp页面的内容2</h1>
    15   </body>
    16 </html>
    复制代码

      运行效果如下:

     

    3.3、控制jsp页面内容重复执行

      编写一个类实现Iterationtag接口,控制doAfterBody()方法的返回值,如果这个方法返回EVAL_BODY_AGAIN, 则web服务器又执行一次标签体,依次类推,一直执行到doAfterBody方法返回SKIP_BODY,则标签体才不会重复执行。

    示例代码如下:

    TagDemo3.java

    复制代码
     1 package me.gacl.web.tag;
     2 
     3 import javax.servlet.jsp.JspException;
     4 import javax.servlet.jsp.tagext.IterationTag;
     5 import javax.servlet.jsp.tagext.Tag;
     6 import javax.servlet.jsp.tagext.TagSupport;
     7 
     8 public class TagDemo3 extends TagSupport {
     9 
    10     int x = 5;
    11     @Override
    12     public int doStartTag() throws JspException {
    13         return Tag.EVAL_BODY_INCLUDE;
    14     }
    15     
    16     /* 控制doAfterBody()方法的返回值,
    17      * 如果这个方法返回EVAL_BODY_AGAIN, 则web服务器又执行一次标签体,
    18      * 依次类推,一直执行到doAfterBody方法返回SKIP_BODY,则标签体才不会重复执行。
    19      * @see javax.servlet.jsp.tagext.TagSupport#doAfterBody()
    20      */
    21     @Override
    22     public int doAfterBody() throws JspException {
    23         x--;
    24         if(x>0){
    25             return IterationTag.EVAL_BODY_AGAIN;
    26         }else{
    27             return IterationTag.SKIP_BODY;
    28         }
    29     }
    30 
    31 }
    复制代码

      在WEB-INF目录下的tld文件中添加对该标签处理类的描述,如下:

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

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

    复制代码
     1 <%@ page language="java" pageEncoding="UTF-8"%>
     2 <%--在jsp页面中导入自定义标签库 --%>
     3 <%@taglib uri="/gacl" prefix="gacl" %>
     4 <!DOCTYPE HTML>
     5 <html>
     6   <head>
     7     <title>控制页面内容重复执行5次</title>
     8   </head>
     9   
    10   <body>
    11   <%--在jsp页面中使用自定义标签 demo3标签--%>
    12       <gacl:demo3>
    13           <h3>jsp页面的内容</h3>
    14       </gacl:demo3>
    15   </body>
    16 </html>
    复制代码

      运行效果如下:

      

    3.4、修改jsp页面内容输出

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

      SUN公司针对BodyTag接口提供了一个默认的实现类BodyTagSupport,BodyTagSupport类中实现了BodyTag接口的所有方法,因此我们可以编写一个类继承BodyTagSupport类,然后再根据需要重写doStartTag方法和doEndTag()方法。

    示例代码如下:

    TagDemo4.java

    复制代码
     1 package me.gacl.web.tag;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.jsp.JspException;
     6 import javax.servlet.jsp.tagext.BodyContent;
     7 import javax.servlet.jsp.tagext.BodyTag;
     8 import javax.servlet.jsp.tagext.BodyTagSupport;
     9 import javax.servlet.jsp.tagext.Tag;
    10 
    11 /**
    12  * @author gacl
    13  * BodyTagSupport类实现了BodyTag接口接口,TagDemo4继承 BodyTagSupport类
    14  */
    15 public class TagDemo4 extends BodyTagSupport {
    16 
    17     /* 控制doStartTag()方法返回EVAL_BODY_BUFFERED
    18      * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
    19      */
    20     @Override
    21     public int doStartTag() throws JspException {
    22         return BodyTag.EVAL_BODY_BUFFERED;
    23     }
    24     
    25     @Override
    26     public int doEndTag() throws JspException {
    27         
    28         //this.getBodyContent()得到代表标签体的bodyContent对象
    29         BodyContent bodyContent = this.getBodyContent();
    30         //拿到标签体
    31         String content = bodyContent.getString();
    32         //修改标签体里面的内容,将标签体的内容转换成大写
    33         String result = content.toUpperCase();
    34         try {
    35             //输出修改后的内容
    36             this.pageContext.getOut().write(result);
    37         } catch (IOException e) {
    38             throw new RuntimeException(e);
    39         }
    40         
    41         return Tag.EVAL_PAGE;
    42     }
    43 }
    复制代码

      在WEB-INF目录下的tld文件中添加对该标签处理类的描述,如下:

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

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

    复制代码
     1 <%@ page language="java" pageEncoding="UTF-8"%>
     2 <%--在jsp页面中导入自定义标签库 --%>
     3 <%@taglib uri="/gacl" prefix="gacl" %>
     4 <!DOCTYPE HTML>
     5 <html>
     6   <head>
     7     <title>修改jsp页面内容输出</title>
     8   </head>
     9   
    10   <body>
    11   <%--在jsp页面中使用自定义标签 demo4标签--%>
    12       <gacl:demo4>
    13           <h3>xdp_gacl</h3>
    14       </gacl:demo4>
    15   </body>
    16 </html>
    复制代码

      运行效果如下:

      

    四、jsp传统标签开发总结

      在现在的jsp标签开发中,很少直接使用传统标签来开发了,目前用得较多的都是简单标签,所以Jsp的传统标签开发了解一下即可,下一篇重点介绍jsp简单标签的开发

  • 相关阅读:
    /etc/sysctl.conf 控制内核相关配置文件
    python 并发编程 非阻塞IO模型
    python 并发编程 多路复用IO模型
    python 并发编程 异步IO模型
    python 并发编程 阻塞IO模型
    python 并发编程 基于gevent模块 协程池 实现并发的套接字通信
    python 并发编程 基于gevent模块实现并发的套接字通信
    python 并发编程 io模型 目录
    python 并发编程 socket 服务端 客户端 阻塞io行为
    python 并发编程 IO模型介绍
  • 原文地址:https://www.cnblogs.com/telwanggs/p/5337794.html
Copyright © 2011-2022 走看看