分享

带有body的自定义tag的开发过程

 kunge 2007-01-17
带有body的自定义tag的开发过程


今天学习带body的自定义标签,尝试写一个标签,这个标签可以迭代显示标签主体里面的内容,迭代的次数由标签的属性指定.

      首先,要说明的是,其实标签也是一个java类,它是运行一个或两个接口的javabean,然后再配合标签描述文件(以.tld为扩展名),两者结合就可以作出自己的自定义标签库了.呵呵,是不是觉得有点眉目了?

      那么下面我们开始写一个自己的java标签类,作为有body的标签,这个类必须实现javax.servlet.jsp.tagext.BodyTag接口.

      下面我们看一下BodyTag这个接口中定义了那些方法来支持tag:

    public void doInitBody();
    public void setBodyContent(javax.servlet.jsp.tagext.BodyContent);
    public int doAfterBody();

      那么由于BodyTag继承了javax.servlet.jsp.tagext.Tag接口,所以我们再来看一下Tag中的方法:

    public void release();
    public javax.servlet.jsp.tagext.Tag getParent();
    public void setParent(javax.servlet.jsp.tagext.Tag);
    public int doEndTag();
    public int doStartTag();
    public void setPageContext(javax.servlet.jsp.PageContext);

      说了这么多方法,是不是有点头晕了?呵呵,那么究竟BodyTag的处理过程是怎么样的呢?下面我们就来说一下它的处理流程:

    1.当容器创建一个新的标签实例后,通过setPageContext来设置标签的页面上下文.
    2.使用setParent方法设置这个标签的上一级标签,如果没有上一级嵌套,设置为null.
    3.设置标签的属性,这个属性在标签库描述文件中定义,如果没有定义属性,就不调用此类方法.
    4.调用doStartTag方法,这个方法可以返回EVAL_BODY_INCLUDE和SKIP_BODY,当返回EVAL_BODY_INCLUDE时,就计算标签的body,如果返回SKIP_BODY,就不再计算标签的body.
    5.调用setBodyContent设置当前的BodyContent.
    6.调用doInitBody,如果计算BodyContent时需要进行一些初始化,就在这个方法中进行.
    7.每次计算完Body后调用doAfterBody,如果返回EVAL_BODY_TAG,表示继续计算一次Body,知道返回SKIP_BODY才继续往下执行.
    8.调用doEndTag方法,这个方法可以返回EVAL_PAGE或者SKIP_PAGE,当返回EVAL_PAGE时,容器将在标签结束时继续计算JSP页面其他的部分;如果返回SKIP_PAGE,容器将在标签结束时停止计算JSP页面其他的部分.
    9.调用release()方法释放标签程序占用的任何资源。

      知道了标签处理的流程了,那么下面我们就开始写一个自己的java类了

      我的标签类的源码:

  1. package test.jsp.tags;
  2. import javax.servlet.jsp.tagext.BodyTagSupport;
  3. import javax.servlet.jsp.tagext.BodyContent;
  4. import javax.servlet.jsp.JspTagException;
  5. public class BodyTagExample
  6.     extends BodyTagSupport {
  7.   private int counts;
  8.   public BodyTagExample() {
  9.     super();
  10.   }
  11.   public void setCounts(int counts) {
  12.     this.counts = counts;
  13.   }
  14.   public int doStartTag() throws JspTagException {
  15.     System.out.println("doStartTag...");
  16.     if (counts > 0) {
  17.       return EVAL_BODY_TAG;
  18.     }
  19.     else {
  20.       return SKIP_BODY;
  21.     }
  22.   }
  23.   public void setBodyContent(BodyContent bodyContent) {
  24.     System.out.println("setBodyContent...");
  25.     this.bodyContent = bodyContent;
  26.   }
  27.   public void doInitBody() throws JspTagException {
  28.     System.out.println("doInitBody....");
  29.   }
  30.   public int doAfterBody() throws JspTagException {
  31.     System.out.println("do After body..." + counts);
  32.     if (counts > 1) {
  33.       counts--;
  34.       return EVAL_BODY_TAG;
  35.     }
  36.     else {
  37.       return SKIP_BODY;
  38.     }
  39.   }
  40.   public int doEndTag() throws JspTagException {
  41.     System.out.println("do end Tag...");
  42.     try {
  43.       if (bodyContent != null) {
  44.         bodyContent.writeOut(bodyContent.getEnclosingWriter());
  45.       }
  46.     }
  47.     catch (java.io.IOException e) {
  48.       throw new JspTagException("IO Error: " + e.getMessage());
  49.     }
  50.     return EVAL_PAGE;
  51.   }
  52. }


      写完了java类,下面我们该用一个描述文件来描述我们写的这个类了:

      我的tld描述文件源码:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
  "http://java./j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>

  <shortname>Application Tag Library</shortname>
  <uri>http://jakarta./taglibs/struts-example-1.0</uri>
  <info>tag loop</info>

    <tag>
    <name>loop</name>
    <tagclass>test.jsp.tags.BodyTagExample</tagclass>
    <bodycontent>JSP</bodycontent>
    <attribute>
    <name>counts</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    </attribute>
   </tag>

</taglib>

      我们对这个文件进行一个小小的说明:

      最重要的是上面的黑体字部分,其他的部分我们可以拷贝粘贴就可以了。

    tag中的name属性:定义了我们的tag名称,在后面会用到。
    tag中的tagclass属性:指定了我们这个tag的实现类。
    tage中的bodycontent属性:指定我们的页面内容是什么性质的。(注意:在jsp开发中这里必须写JSP)
    tage中的attribute属性:定义了我们的这个tag可能有的属性。

    attribute中的name属性:指定了属性的名称。它和我们类中定义的“int counts;”必须一样,并且在类中还必须包含一个setCounts(int counts)方法,否则这个属性就不能设置。
    attribute中的required属性:表示这个属性是否是必须的。
    attribute中的rtexprvalue属性:表示这个属性是否可以用JSP的程序段的结果输出。

      现在我们的tag就写完了,下面就是我们怎么在页面中用了。

      首先,我们要在web.xml中声明这个tag

    我的web.xml源码:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java./dtd/web-app_2_3.dtd">
  3. <web-app>
  4.   <taglib>
  5.     <taglib-uri>demotag</taglib-uri>
  6.     <taglib-location>/WEB-INFtldmytag.tld</taglib-location>
  7.   </taglib>
  8. </web-app>

  
      其次,我们要在页面中引用这个tag。

      我的jsp源码:

  1. <%@ page contentType="text/html; charset=GBK" language="java"%>
  2. <%@ taglib uri="demotag" prefix="demo" %>
  3. <html>
  4. <body>
  5.     <br>
  6.     <demo:loop counts="5">
  7.         现在时间是:<%=new java.util.Date().toString()%><br>
  8.     </demo:loop>
  9.     <br>
  10. </body>
  11. </html>


      好了,一个tag就开发完了,下面是页面的显示结果:

现在时间是:Thu Sep 22 12:33:31 CST 2005
现在时间是:Thu Sep 22 12:33:31 CST 2005
现在时间是:Thu Sep 22 12:33:31 CST 2005
现在时间是:Thu Sep 22 12:33:31 CST 2005
现在时间是:Thu Sep 22 12:33:31 CST 2005

      这里是后台打出来的信息:

doStartTag...
setBodyContent...
doInitBody....
do After body...5
do After body...4
do After body...3
do After body...2
do After body...1
do end Tag...

      一切OK了!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多