gdufo

           

          jsp自定義標(biāo)簽(taglib)編寫的原理和實(shí)現(xiàn)

          轉(zhuǎn):http://www.javaeye.com/topic/157737

          個(gè)tag就是一個(gè)普通的java類,它惟一特別之處是它必須繼承TagSupport或者BodyTagSupport類。這兩個(gè)類提供了一些方法,負(fù)責(zé)jsp頁面和你編寫的類之間的交互,例如輸入,輸出。而這兩個(gè)類是由jsp容器提供的,無須開發(fā)人員自己實(shí)現(xiàn)。換句話說,你只需把實(shí)現(xiàn)了業(yè)務(wù)邏輯的類繼承TagSupport或者BodyTagSupport,再做一些特別的工作,你的類就是一個(gè)Tag。并且它自己負(fù)責(zé)和jsp 頁面的交互,不用你多操心。

          “特別的工作”通常有以下幾個(gè)步驟:

          [1]提供屬性的set方法,此后這個(gè)屬性就可以在jsp頁面設(shè)置。以jstl標(biāo)簽為例 c:out value=""/,這個(gè)value就是jsp數(shù)據(jù)到tag之間的入口。所以tag里面必須有一個(gè)setValue方法,具體的屬性可以不叫value。例如setValue(String data){this.data = data;}
          這個(gè)“value”的名稱是在tld里以attribute元素存在的。
          取什么名字都可以,只需tag里提供相應(yīng)的set方法即可。

          [2]處理 doStartTag 或 doEndTag 。這兩個(gè)方法是 TagSupport提供的。 還是以c:out value=""/為例,當(dāng)jsp解析這個(gè)標(biāo)簽的時(shí)候,在“<”處觸發(fā) doStartTag 事件,在“>”時(shí)觸發(fā) doEndTag 事件。通常在 doStartTag 里進(jìn)行初始化,流程選擇操作,在 doEndTag 里后續(xù)頁面輸出控制。
          [3]編寫tld文件,就是把編寫的tag組件的信息以mxl形式告訴容器,它才好以一定步驟解釋tag組件
          [4]在jsp頁面導(dǎo)入tld。這樣,你的jsp頁面就可以使用自己的tag組件了。

          通常你會(huì)發(fā)現(xiàn)自己絕大多數(shù)活動(dòng)都集中在 doStartTag 或 doEndTag方法里,如果在服務(wù)器端處理標(biāo)簽中的正文或則是嵌套標(biāo)簽時(shí)的話,還是過問一下doAfterBody。
          一個(gè)簡(jiǎn)單的例子:OutputTag

          package test;
          import javax.servlet.jsp.JspException;
          import javax.servlet.jsp.JspWriter;
          import javax.servlet.jsp.tagext.TagSupport;

          public class OutputTag extends TagSupport {
          private String name=null;
          public void setName(String name) {
          this.name = name;
          }
          public int doEndTag() throws JspException
          {
          try {
          JspWriter out = pageContext.getOut();
          out.print("Hello! " + name);
            } catch (Exception e) { throw new JspException(e); }
          return EVAL_PAGE;
          }
          }

          簡(jiǎn)要說明:
          1 如何輸出到j(luò)sp頁面:調(diào)用JspWriter JspWriter out = pageContext.getOut();out.print......記住這個(gè)方法就可以了。
          2 輸出后如何作處理,函數(shù)會(huì)返回幾個(gè)值之一。EVAL_PAGE 表示tag已處理完畢,返回jsp頁面。還有幾個(gè)值,例如 EVAL_BODY_AGAIN 和EVAL_BODY_INCLUDE等 跟流程控制有關(guān).

          編寫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">
          <taglib>
          <tlib-version>1.0</tlib-version>
          <jsp-version>1.2</jsp-version>
          <short-name>test</short-name>
          <!--OutputTag-->
          <tag>
          <name>out</name>
          <tag-class>test.OutputTag</tag-class>
          <body-content>empty</body-content>
          <attribute>
          <name>name</name>
          <required>false</required>
          <rtexprvalue>false</rtexprvalue>
          </attribute>
          </tag>
          </taglib>

          在WEB-INF下新建tlds文件夾,把這個(gè)文件取名為test.tld,放到tlds文件夾下。引用時(shí)的路徑應(yīng)該這樣:WEB-INF\tlds\test.tld

          關(guān)于tld的簡(jiǎn)單說明:
          short-name:taglib的名稱,也稱為前綴。比如“c:out value=""/” 里的“c”
          name:tag的名字。例如“c:out value=""/” 里的"out”,我們的類也取名為out,由于有前綴作區(qū)分,不會(huì)同其他庫的同名tag組件混淆
          tag-class:完整的tag組件路徑,記著帶包名
          body-content:指tag之間的內(nèi)容。例如c:out value="" ...... /c 起始和關(guān)閉標(biāo)簽之間就是body-content。由于沒有處理body-content ,所以上面設(shè)為empty,如果是嵌套標(biāo)簽,或則是要在服務(wù)器端處理標(biāo)簽體的話,就是jsp了
          “attribute”里的name:屬性名字。例如c:out value=""/里的value。名字可任意取,只要類里提供相應(yīng)的set方法即可。
          required:是否必填屬性。
          rtexprvalue:是否支持運(yùn)行時(shí)表達(dá)式取值就是是否可以<%=%>或則是${}方式傳值。
          這是tag的強(qiáng)大功能。
          編寫jsp頁面

          <%@ page language="java"%>
          <%@ taglib uri="/WEB-INF/tlds/test.tld" prefix="test"%>
          <html>
          <body>
          Test Tag: <test:out name="TEST"/>
          </body>
          </html>

          啟動(dòng)服務(wù)器,如果一切按照上面步驟的話,就能看到 Test Tag: Hello! TEST 字樣。最簡(jiǎn)單的tag就這么出來了。并不難,是不是?
          ------------------------------------------------------------------
          Tag系列的Interface里定義的靜態(tài)int,通過他們也能一窺tag組鍵的執(zhí)行流程,這幾個(gè)靜態(tài)值分別是:
          SKIP_BODY : 跳過了開始和結(jié)束標(biāo)簽之間的代碼,一般是在doStartTag中使用
          EVAL_BODY_INCLUDE :處理嵌套的標(biāo)簽,一般是在doStartTag中使用,由負(fù)責(zé)處理標(biāo)簽正文的tag接口提供
          EVAL_BODY_BUFFERED :對(duì)包含的內(nèi)容進(jìn)行解析 一般是在doStartTag中使用,由負(fù)責(zé)處理標(biāo)簽正文的bodyTag接口提供,目的是通知jsp容器作好讀取正文的工作(創(chuàng)建一個(gè)body-content包裝正文和獲取存放操作結(jié)果的out對(duì)象,便于以后的操作和輸出).
          EVAL_BODY_AGAIN:處理標(biāo)簽正文,嵌套標(biāo)簽的iteratorTag接口的使用
          SKIP_PAGE : 忽略剩下的頁面,一般是在doEndTag中使用
          EVAL_PAGE : 繼續(xù)執(zhí)行下面的頁, 一般是在doEndTag中使用

          posted on 2008-09-04 15:31 gdufo 閱讀(4294) 評(píng)論(1)  編輯  收藏 所屬分類: JAVA 基礎(chǔ)

          評(píng)論

          # aa[未登錄] 2016-05-25 13:53 bb

          1111  回復(fù)  更多評(píng)論   

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(6)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          收藏夾

          Hibernate

          友情鏈接

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 临城县| 高碑店市| 永顺县| 涿鹿县| 桃园市| 琼海市| 德兴市| 东乡族自治县| 土默特右旗| 睢宁县| 舟曲县| 阿城市| 隆德县| 安泽县| 济阳县| 阳山县| 阿克苏市| 泾源县| 武陟县| 浏阳市| 南京市| 涪陵区| 鲁山县| 舞钢市| 玉门市| 中西区| 剑阁县| 平湖市| 金塔县| 隆化县| 屯昌县| 呈贡县| 如皋市| 福建省| 武山县| 锡林郭勒盟| 江孜县| 宝山区| 宜君县| 潼关县| 钟山县|