一個簡單的帶Body的自定義Tag開發過程

2005-10-19 12:08:34
 
JasonDong2005-09-28
 
      今天學習帶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類了
      我的標籤類的源碼:
 
package test.jsp.tags;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.JspTagException;
public class BodyTagExample
    extends BodyTagSupport {
  private int counts;
  public BodyTagExample() {
    super();
  }
  public void setCounts(int counts) {
    this.counts = counts;
  }
  public int doStartTag() throws JspTagException {
    System.out.println("doStartTag...");
    if (counts > 0) {
      return EVAL_BODY_TAG;
    }
    else {
      return SKIP_BODY;
    }
  }
  public void setBodyContent(BodyContent bodyContent) {
    System.out.println("setBodyContent...");
    this.bodyContent = bodyContent;
  }
  public void doInitBody() throws JspTagException {
    System.out.println("doInitBody....");
  }
  public int doAfterBody() throws JspTagException {
    System.out.println("do After body..." + counts);
    if (counts > 1) {
      counts--;
      return EVAL_BODY_TAG;
    }
    else {
      return SKIP_BODY;
    }
  }
  public int doEndTag() throws JspTagException {
    System.out.println("do end Tag...");
    try {
      if (bodyContent != null) {
        bodyContent.writeOut(bodyContent.getEnclosingWriter());
      }
    }
    catch (java.io.IOException e) {
      throw new JspTagException("IO Error: " + e.getMessage());
    }
    return EVAL_PAGE;
  }
}

      寫完了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.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>Application Tag Library</shortname>
  <uri>http://jakarta.apache.org/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源碼:
 
<?xml version="1.0" encoding="UTF-8"?>
<!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>demotag</taglib-uri>
    <taglib-location>/WEB-INFtldmytag.tld</taglib-location>
  </taglib>
</web-app>

      其次,我們要在頁面中引用這個tag。
      我的jsp源碼:
 
<%@ page contentType="text/html; charset=GBK" language="java"%>
<%@ taglib uri="demotag" prefix="demo" %>
<html>
<body>
    <br>
    <demo:loop counts="5">
        現在時間是:<%=new java.util.Date().toString()%><br>
    </demo:loop>
    <br>
</body>
</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了!
      程序很簡單,但是希望以此來向大家展示一個tag的基本開發流程,如果有不對的地方,希望大家批評指正!謝謝!
 
 
http://www.javaresearch.org/article/showarticle.jsp?column=106&thread=37680

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章