tld標籤學習經典教程

一、概述

 

JSP 2.0 中提供了兩種新的開發自定義標記的方法:

1、簡單標籤機制SimpleTag

JSP 2.0 中加入了新的創建自定義標記的API:javax.servlet.jsp.tagext.SimpleTag,該API 定義了用來實現簡單標記的接口。和JSP 1.2 中的已有接口不同的是,SimpleTag 接口不使用doStartTag()和doEndTag()方法,而提供了一個簡單的doTag()方法。這個方法在調用該標記時只被使用一次。一個自定義標記中實現的所有邏輯都在這個方法中實現。相對JSP1.2 中自定義標記機制,SimpleTag 的方法和處理週期要簡單得多。

 

2、 標籤文件

標籤文件允許JSP 網頁作者使用JSP 語法創建可複用的標籤庫。標籤文件的擴展名必須是.tag。

 

1.1 使用簡單標籤機制

與JSP1.2 相似,開發自定義標籤要遵循“開發標記類---配置TLD 文件----在JSP 中使用”的過程,

示例如下:

步驟一:編寫標記處理類AddTag.java

package tag;

 

import java.io.IOException;

 

import javax.servlet.jsp.JspContext;

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.tagext.SimpleTagSupport;

 

public class AddTag extends SimpleTagSupport{

         private int num1 = 0;

         private int num2 = 0;

         public void setNum1(int num1) {

                   this.num1 = num1;

         }

         public void setNum2(int num2) {

                   this.num2 = num2;

         }

         public void doTag() throws JspException, IOException {

                   JspContext ctx = getJspContext();

                   JspWriter out = ctx.getOut();

                   int sun = num1+num2;

                   out.print(num1+"+"+num2+"="+sun);

         }

}

 

步驟二:編寫描述符文件 test.tld:放在/WEB-INF/test-tld/test.tld

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

<!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><!-- 標籤定義成<test:add /> -->

    <tlibversion>1.0</tlibversion>

    <jspversion>1.2</jspversion>

    <shortname>test</shortname><!-- 這個test可以設置爲空,你標籤就可以定義成<add />了,不過一般比較常見的都是<test:add />這種類型的 -->

    <tag>

       <name>add</name>

       <tagclass>tag.AddTag</tagclass>

       <bodycontent>empty</bodycontent><!-- 就是<test:add ></test>中間的內容是空的 -->

       <info>Add Tag</info>

       <attribute>

           <name>num1</name>

           <required>true</required>

           <rtexprvalue>true</rtexprvalue>

       </attribute>

       <attribute>

           <name>num2</name>

           <required>true</required>

           <rtexprvalue>true</rtexprvalue>

       </attribute>

    </tag>

</taglib>

 

 

步驟三:在JSP 中使用標記:

<%@ page language="java"   pageEncoding="UTF-8"%>

<%@ taglib prefix="test" uri="/WEB-INF/test-tld/test.tld" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>測試自定義標籤</title>

  </head>

  <body>

        SimpleTag 測試:<br />

        <h1><test:add num1="2" num2="3"/></h1>

  </body>

</html>

 

無需在web.xml下配置,

運行結果如下:

 

 

 

 

 

 
  

1.2 使用標籤文件

通過標籤文件實際上可以將一個JSP 文件的內容作爲標籤處理程序,但該文件擴展名必須是.tag,

示例如下:

1) 標記文件hello.tag,該文件存放在 WEB-INF/tags 目錄下

hello.tag.<br>

IP:<%= request.getRemoteAddr() %>

2) 在JSP 中使用tag 文件

<%@ page contentType="text/html;charset=gb2312" %>

<%@ taglib prefix="test" tagdir="/WEB-INF/tags/" %>

<h2>Tag File 測試</h2>

<test:hello/>

3) 運行效果如下:

 

二 、自定義標籤簡介

 

2.1 自定義標籤概念

 

JSP標籤分爲標準JSP 環境自帶的標籤(即前面章節中學習過的JSP 動作標籤)和JSP 自定義標籤。JSP 自定義標籤是用戶定義的標記,它遵循XML 語法。當servlet 容器處理自定義標記時,會自動調用一個Java 類文件完成相對應的功能。

Java 開發人員編寫標記處理程序類以處理標記並處理所有需要的Java 代碼和數據操作。對於Web頁面設計者來說,自定義標記與標準HTML 標記使用起來沒什麼區別,但HTML 標記只能完成前臺顯示的功能,而自定義標記可以在後臺完成某些操作。

正確編寫自定義標記可以讓 Web 設計者創建、查詢和操作數據而無需編寫一行Java 代碼。正確使用自定義標記使 Java 開發人員不必再在編碼過程中考慮表示層。這樣應用程序開發小組的每一位成員都可以關注於他或者她最擅長的事物。

所以說,JSP 自定義標記爲在動態Web 頁中將表示與業務邏輯分離提供了一種標準化的機制,使頁面設計者可以將注意力放到表示上,而應用程序開發人員編寫後端的代碼。

 

2.2 標籤相關概念

JSP 自定義標籤的使用語法與普通HTML標籤相同,與自定義標籤相關的基本術語簡單說明如下,

這些術語在開發JSP 自定義標籤時要用到:

1) 自結束標籤——沒有標記體的標籤

示例:<test:myhrtag />

說明:假設myhrtag 是一個自定義標籤

2) 屬性

示例:<test:myhrtag color=”red” />

說明:以上標籤中包含了color 屬性,值爲red

3) 帶標記體的標籤

示例:<test:myhrtag > xxxxx </test:myhrtag>

說明:以上標籤中間的xxxxx 即爲標記體

4) 子標記

示例: <test:myhrtag >

<test:mytag2/>

</test:myhrtag>

說明:以上myhrtag 標籤中間的mytag2 即爲子標記

 

 

2.3 如何創建自定義標籤

 

自定義標籤功能的實現要求在後臺必須有一個相關的JAVA 類的支持,但並不是任意編寫一個JAVA 類就能處理JSP 標籤,這個類也必須實現指定的規範才能用於支持JSP 標籤,這些規範表現形式也是接口和類,它們在javax.servlet.jsp.tagext包中聲明,主要接口/類的描述如下:

javax.servlet.jsp.tagext.Tag 接口,所有處理JSP 標籤的類必須實現該接口。該接口中聲明瞭6個方法,如果直接從該接口生成類則必須實現所有的6 個方法,通常不會直接通過該接口生成標籤的處理類。

 javax.servlet.jsp.tagext.TagSupport 類,該類實現了Tag 接口,用於創建不帶標記體的自結束標籤,這些標籤中可以帶屬性。

javax.servlet.jsp.tagext.BodyTagSupport 類,該類繼承了TagSupport,用於創建帶標記體的標籤。

    通常我們自定義的標籤,編寫處理程序時使用TagSupport 和BodyTagSupport 即可,不需要涉及到標籤體的,繼承TagSupport,需要用標籤體的,用BodyTagSupport,以下是開發和使用一個JSP 自定義標籤的全過程:

1) 開發標記處理類,編譯生成class 文件,該類要繼承TagSupport 或BodyTagSupport;

2) 創建標記庫描述符文件*.tld,在該文件中爲標記處理類指定標籤名、聲明標籤屬性;

3) 在JSP 中引用標籤庫;

4) 在JSP 中使用標JSP 標籤

 

三、自結束標籤(不帶標籤體,TagSupport)

3.1 自結束標籤簡介

這是一種不帶標記體的標籤,所以該類標籤的處理類直接繼承javax.servlet.jsp.tagext.TagSupport即可。TagSupport 的主要方法如下:

public int doStartTag() throws JspException

在WEB 容器遇到標籤開始時,該方法會運行。

public int doEndTag() throws JspException

在WEB 容器遇到標籤結束時,該方法會運行。

         TagSupport 類中有一個重要的成員:pageContext,該成員的功能與JSP 的內置對象pageContex完全相同。通過該對象可以得到其他幾個JSP 對象的引用。這樣,我們就可以在JAVA 類中與JSP 進行交互了。如: JspWriter out=pageContext.getOut();這一語句可以得到JSP 內置對象out 的引用,通過out 我們就可以向客戶端瀏覽器中輸出內容了。要使用其他幾個JSP 對象原理與此相同。

 

3.2自結束標籤開發示例

 

方式二:動態引用

步驟一:編寫標記處理類

package tag;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.tagext.Tag;

import javax.servlet.jsp.tagext.TagSupport;

 

/**

 *自定義自結束標籤,不含標籤體。

 *

 *1、在自定義的類中,重寫了父類TagSupport的兩個方法:doStartTag()doEndTag(),在容器遇到標記開始時會運行doStartTag(),遇到標記結束時運行doEndTag()方法;

 *2doStartTag()方法的返回值:通常可以取兩個值:

 *      EVAL_BODY_INCLUDE——包含標記體,本例中要編寫自結束標記所以不使用該值;

 *      SKIP_BODY——跳過標記體,即不處理標記體,開發自結束標記應該使用該值。

 *3doEndTag()方法的返回值:通常可以取兩個值:

 *      SKIP_PAGE——返回這個值,則終止頁面執行;

 *      EVAL_PAGE——返回該值則處理完當前標記後,JSP頁面中止運行。

 */

 

publicclass MyHrTag extends TagSupport{

 

    /**

     *

     */

    privatestaticfinallongserialVersionUID = 1L;

 

    /*

     * WEB 容器遇到標籤開始時,該方法會運行。

     * 該方法可以自行定義,也可以不定義。不定義該方法則遇到開始標籤什麼都不做

     * */

    publicint doStartTag() throws JspException {

       try {

           //得到網絡輸出流,pageContext 是從父類繼承過來的成員

           JspWriter out = pageContext.getOut();

           //向網頁輸出內容

           out.println("<h4>開始執行doStartTag()......</h4>");

           //輸出條水平線;

           for(int i=1; i<=5; i++){

              out.println("<hr>");

           }

       catch (Exception e) {

           e.printStackTrace();

       }

       //return EVAL_BODY_INCLUDE; //處理標記體

       return Tag.SKIP_BODY//跳過標記體;

    }

   

    /*

     * WEB 容器遇到標籤結束時,該方法會運行。

     * 該方法可以自行定義,也可以不定義。不定義該方法則遇到結束標籤什麼都不做

     * */

    publicint doEndTag() throws JspException {

       try {

           JspWriter out=pageContext.getOut();

           out.println("<h3>開始執行doEndTag().....</h3>.");

       catch (Exception e) {

           e.printStackTrace();

       }

       //return Tag.SKIP_PAGE; //返回這個值,則終止頁面執行;

       returnEVAL_PAGE;

    }

}

 

步驟二:創建標記庫描述符文件myhr.tld,該文件要存放在 WEB-INF/test-tld 目錄下:

 

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

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">    

<!--

解釋:

tld 文件中,映射了標記名和處理程序類;

<tallib>元素,代表開始一個標記庫的描述

<tligversion>元素,代表標記庫的版本

<jspversion>元素,代表標記所支持的JSP 的版本

<shortname>爲標記庫起別名,相當於註釋,無實際用途

<tag>元素,代表開始描述一個標記,其下子元素如下:

    <name>——爲標記處理類起的標記名

    <tagclass>——指定標記處理類的全名(即帶包的名字)

    <bodycontent>——標記體的類型,該示例中不需要標記體,所有設置爲EMPTY,該值的其他取值在後續內容中講解

 -->

<taglib>

    <tlibversion>1.0</tlibversion>

    <jspversion>1.1</jspversion>

    <shortname>myhr</shortname><!-- 標籤以<myhr:XXX />形式 -->

    <tag>

       <name>MyHr</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.MyHrTag</tagclass>

       <bodycontent>EMPTY</bodycontent>

    </tag>

</taglib>

 

 

步驟三:在JSP 中引用標記庫描述文件

引用標記庫有兩種方式,分別稱爲靜態引用和動態引用。

方式一:動態引用(即直接在JSP 頁面中使用TLD 文件)

<%@ page language="java"  pageEncoding="UTF-8"%>

<%@ taglib uri="/WEB-INF/test-tld/myhr.tld" prefix="myhr" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>My JSP 'MyHr1.jsp' starting page</title>

  </head>

  <body>

   <myhr:MyHr/>

  </body>

</html>

 

JSP 指令<%@ taglib... %>用於引用標記庫,該指令的兩個屬性作用如下:

uri——指明要引用的標記庫,在靜態引用中就是TLD 文件的路徑

prefix——爲標記起的前綴名,可以防止多個標記重名的情況出現

 

方式二:靜態引用

首先在web.xml 中爲TLD 文件聲明別名:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<Web-app>

……

<taglib>

<taglib-uri>myhr2</taglib-uri>

<taglib-location>/WEB-INF/myhr.tld</taglib-location>

</taglib>

……

</Web-app>

然後在JSP 中通過別名引用TLD 文件:

<%@ page language="java"  pageEncoding="UTF-8"%>

<%@ taglib uri="myhr2" prefix="myhr" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>My JSP 'MyHr1.jsp' starting page</title>

  </head>

  <body>

   <myhr:MyHr/>

  </body>

</html>

到此爲止,自結束標籤開發完畢,其中主要工作有兩個:開發標記處理類、配置TLD 文件。訪

問JSP,運行結果如下:

 

 

四、標籤中的屬性

4.1 爲自定義標籤添加屬性

以上的示例中開發了一個簡單的JSP 標籤,但一個實用的標籤通常還要由屬性來制定標籤的特定行爲,以下示例演示爲自定義標籤添加屬性。該示例在1.2 示例基礎上,爲標籤添加了color 和loop兩個自定義屬性,以控制水平線的顏色和輸出的水平線的數量。

步驟一:編寫標記處理類

package tag;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.tagext.Tag;

import javax.servlet.jsp.tagext.TagSupport;

 

/**

 *

 *該類爲自定義標籤添加了兩個屬性,屬性的聲明與javabean語法完全相同,即屬性本身是private類型,

 *但要求提供publicgetset方法。

 * 

 */

 

publicclass MyHrTag2 extends TagSupport{

   

    //聲明屬性

    private String color = "black"//定義線條顏色

    private String loop = "1"//定義輸出水平線的條數

   

    //嚴格按照javabean模式

    publicvoid setColor(String color) {

       this.color = color;

    }

   

    //嚴格按照javabean模式

    publicvoid setLoop(String loop) {

       this.loop = loop;

    }

   

    //只定義遇到開始標籤執行方法即可了。

    publicint doStartTag() throws JspException {

       try {

           //得到網絡輸出流

           JspWriter out = pageContext.getOut();

           //向網頁輸出內容;

           out.println("<h4>開始執行doStartTag()......</h4>");

           int n = Integer.parseInt(loop);

           for (int i=1;i<=n;i++) {

              out.print("<hr color='"+this.color+"' />");

           }

       catch (Exception e) {

           e.printStackTrace();

       }

       return Tag.SKIP_BODY;

    }

   

}

 

步驟二:創建TLD 文件,本例中是在1.2 中的myhr.tld 文件中進行修改得到:

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

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">    

<!--

解釋:

   tld 文件中,映射了標記名和處理程序類;

   <tallib>元素,代表開始一個標記庫的描述

   <tligversion>元素,代表標記庫的版本

   <jspversion>元素,代表標記所支持的JSP 的版本

   <shortname>爲標記庫起別名,相當於註釋,無實際用途

   <tag>元素,代表開始描述一個標記,其下子元素如下:

    <name>——爲標記處理類起的標記名

    <tagclass>——指定標記處理類的全名(即帶包的名字)

    <bodycontent>——標記體的類型,該示例中不需要標記體,所有設置爲EMPTY,該值的其他取值在後續內容中講解

    <tag>中的子元素

       <attribute>用於爲標籤聲明屬性,其子元素如下:

           <name>——用於指定屬性名稱

           <required>——用於聲明該屬性是否爲必需的,本例中聲明colorloop 兩個屬性都不是必需的。

 -->

<taglib>

    <tlibversion>1.0</tlibversion>

    <jspversion>1.1</jspversion>

    <shortname>myhr</shortname><!-- 標籤以<myhr:XXX />形式 -->

    <tag>

       <name>MyHr</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.MyHrTag</tagclass>

       <bodycontent>EMPTY</bodycontent>

    </tag>

    <tag>

       <name>MyHr2</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.MyHrTag2</tagclass>

       <bodycontent>EMPTY</bodycontent>

       <attribute>

           <name>color</name>

           <required>false</required>

       </attribute>

       <attribute>

           <name>loop</name>

           <required>false</required>

       </attribute>

    </tag>

</taglib>

 

步驟三:在JSP 中引用TLD,並使用標籤

<%@ page language="java"  pageEncoding="UTF-8"%>

<%@ taglib uri="/WEB-INF/test-tld/myhr.tld" prefix="myhr" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>My JSP 'MyHr3.jsp' starting page</title>

  </head>

  <body>

    第一次測試(未賦屬性值):<br>

    <myhr:MyHr2/>

   

    第二次測試(使用兩個屬性):<br>

    <myhr:MyHr2 color="red" loop="3"/>

   

    第三次測試(使用一個屬性):<br>

    <myhr:MyHr2 color="blue"/>

   

    測試完畢.

  </body>

</html>

 

運行圖

 

 

 

4.2 標籤綜合示例

該示例中創建了一個JSP 標籤,用於在JSP 中判斷用戶是否登錄過,如果沒登錄過則自動轉到登錄頁,這樣就可以避免在JSP 中使用代碼段進行業務判斷了。

第一步:定義標籤類LoginTag.java,爲標記處理程序,從session 中取出登錄標誌進行判斷用戶是否登錄過:

package tag;

 

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.Tag;

import javax.servlet.jsp.tagext.TagSupport;

 

publicclass LoginTag extends TagSupport{

 

    publicint doStartTag() throws JspException {

       try {

           HttpSession session = pageContext.getSession();

           Object obj = session.getAttribute("User");

           //判斷是否從未登錄過,如果沒登錄過則轉到登錄頁;

           if(obj==null){

              ((HttpServletResponse)pageContext.getResponse()).sendRedirect("login.html");

              returnSKIP_BODY;

           }

       catch (Exception e) {

           e.printStackTrace();

       }

       return Tag.SKIP_BODY;

    }

}

 

第二步:編寫login.tld

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

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">    

<!--

解釋:

    tld 文件中,映射了標記名和處理程序類;

    <tallib>元素,代表開始一個標記庫的描述

    <tligversion>元素,代表標記庫的版本

    <jspversion>元素,代表標記所支持的JSP 的版本

    <shortname>爲標記庫起別名,相當於註釋,無實際用途

    <tag>元素,代表開始描述一個標記,其下子元素如下:

    <name>——爲標記處理類起的標記名

    <tagclass>——指定標記處理類的全名(即帶包的名字)

    <bodycontent>——標記體的類型,該示例中不需要標記體,所有設置爲EMPTY,該值的其他取值在後續內容中講解

    <tag>中的子元素

       <attribute>用於爲標籤聲明屬性,其子元素如下:

           <name>——用於指定屬性名稱

           <required>——用於聲明該屬性是否爲必需的,本例中聲明colorloop 兩個屬性都不是必需的。

 -->

<taglib>

    <tlibversion>1.0</tlibversion>

    <jspversion>1.1</jspversion>

    <shortname>test</shortname><!-- 標籤以<myhr:XXX />形式 -->

    <tag>

       <name>islogin</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.LoginTag</tagclass>

       <bodycontent>EMPTY</bodycontent>

    </tag>

</taglib>

 

第三步:動態調用標籤

部分內容如下:

<%@ page language="java" contentType="text/html;charset=GB2312"%>

<%@ taglib uri="/WEB-INF/myhr.tld" prefix="test" %>

….

<test:islogin/>

<h3>歡迎</h3>

….

 

 

 

4.3 TLD 文件概述

以上示例中創建了標記描述符文件*.TLD,現總結該文件的用法如下:

該文件必須放在 WEB-INF 目錄下;

該文件是XML 格式的文件,各元素及功能說明如下:

元素    說明

<taglib> 代表開始一個標記庫的描述

<tlibversion> 代表標記庫的版本,是自定義的

<jspversion> 代表標記所支持的JSP 的版本

<shortname> 爲標記庫起別名,相當於註釋,無實際用途

<tag>     代表開始描述一個標記

表11-1 標記描述符TLD 文件元素說明

其中<tag>元素中又包含若干子元素,說明如下:

元素 說明

<name> 爲標記處理類起的標記名

<tagclass> 指定標記處理類的全名(即帶包的名字)

<bodycontent> 標記體的內容類型,如果爲EMPTY 代表無標記體

<attribute> 用於爲標籤聲明屬性

表11-2 <tag>元素的子元素

<attribute>元素爲標籤聲明屬性時,需要兩個子元素:

<name> 用於指定屬性名稱

<required> 用於聲明該屬性是否爲必需的

 

 

五、標籤中的標記體

5.1 標記體簡介

標籤的標記體是 JSP 頁中出現在自定義標籤的開始和結束標籤之間的數據,標記體也稱正文。操縱其正文的標籤稱爲帶標記體的標籤(也稱爲正文標籤)。

可以編寫標籤處理程序對標籤的標記體進行操作。要編寫標記體標籤處理程序,必須實現BodyTag 接口。BodyTag 繼承了Tag 的所有方法,而且還實現了另外兩個處理正文內容的方法,見下表:

                   方法                            說明

setBodyContent(BodyContent b)                 bodyContent 屬性的 Setter 方法

doInitBody()                                             對正文內容進行初始化操作

 

爲方便開發,在JSP 類庫中爲BodyTag 接口提供了實現類:javax.servlet.jsp.tagext.BodyTagSupport。該類繼承了TagSupport 並實現了BodyTag 接口。因此,標記體標籤處理程序只需要覆蓋要使用的方法。BodyTagSupport 類中定義了一個protected bodyContent 成員變量及get/setBodyContent()方法,bodyContent 是一個緩衝區,用以保存標記體正文內容。

在一個標籤處理類中,BodyTag 的處理流程如下:

         1、當容器創建一個新的標籤實例後,通過setPageContext 來設置標籤的頁面上下文。

2、使用setParent 方法設置這個標籤的上一級標籤,如果沒有上一級嵌套,設置爲null。

3、設置標籤的屬性,如果沒有定義屬性,就不調用此類方法。

4、調用doStartTag 方法,這個方法可以返回以下三者之一:EVAL_BODY_INCLUDE、

EVAL_BODY_BUFFERED、SKIP_BODY,當返回EVAL_BODY_INCLUDE 時,就將標記

體直接寫到輸出流中,如果返回SKIP_BODY,就不再計算標籤的正文,如果返回EVAL_BODY_BUFFERED,就將標記體的正文包含到bodyContent 成員中。

5、調用setBodyContent 設置當前的BodyContent.

6、調用doInitBody,可以在該方法中對BodyContent 進行一些初始化操作.每次計算完Body 後調用doAfterBody,如果返回EVAL_BODY_AGAIN,表示繼續處理一次標記體,直到返回SKIP_BODY 才繼續往下執行.

7、調用doEndTag 方法,結束標籤處理.

 

5.2 一個簡單的帶標記體的標籤

 

本示例中創建了一個標籤用於在瀏覽器中輸出其標記體內容,且輸出的次數由標籤的屬性決定:

         步驟一:編寫標記處理類

package tag;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.BodyTagSupport;

 

/**

 *

 *doStartTag()中的返回值EVAL_BODY_INCLUDE,可以直接將標籤的正文內容輸出到瀏覽器中。

 *doAfterBody()在處理完一次正文後會自動執行,

 *該方法如果返回EVAL_BODY_AGAIN,則代表再處理一遍正文(即輸出到瀏覽器),返回SKIP_BODY代表正文處理到此結束。

 *本例中循環向瀏覽器中輸出標記體的正文,直到屬性loop的值小於1

 *

 */

 

publicclass TestBodyTag extends BodyTagSupport {

    privateintloop ; //定義輸出標籤體的次數屬性,比如:2的話就表示連續重複輸出標籤體2

 

    publicvoid setLoop(int loop) {

       this.loop = loop;

    }

 

    publicint doStartTag() throws JspException {

       if(loop>0){

           returnEVAL_BODY_INCLUDE//自動將標籤體包含到輸出流中,第一次將標籤體輸出到瀏覽器中.

       }else {

           returnSKIP_BODY//跳過標籤體,不將標籤體包含到輸出流,不處理標籤體,直接忽略.

       }

    }

 

    publicint doAfterBody() throws JspException {

       /**

        *doAfterBody()在處理完一次正文後會自動執行,

        *該方法如果返回EVAL_BODY_AGAIN,則代表再處理一遍正文(即輸出到瀏覽器),返回SKIP_BODY代表正文處理到此結束。

        *本例中循環向瀏覽器中輸出標記體的正文,直到屬性loop的值小於1

        */

       if(loop>1){

           loop--;

           returnEVAL_BODY_AGAIN;

       }else {

           returnSKIP_BODY;

       }

    }

}

 

步驟二:創建標記庫描述符文件testbodytag.tld,該文件要存放在 WEB-INF/test-tld 目錄下:

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

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">    

<!--

解釋:

    tld 文件中,映射了標記名和處理程序類;

    <tallib>元素,代表開始一個標記庫的描述

    <tligversion>元素,代表標記庫的版本

    <jspversion>元素,代表標記所支持的JSP 的版本

    <shortname>爲標記庫起別名,相當於註釋,無實際用途

    <tag>元素,代表開始描述一個標記,其下子元素如下:

    <name>——爲標記處理類起的標記名

    <tagclass>——指定標記處理類的全名(即帶包的名字)

    <bodycontent>——標記體的類型,該示例中不需要標記體,所有設置爲EMPTY,該值的其他取值在後續內容中講解

    <tag>中的子元素

       <attribute>用於爲標籤聲明屬性,其子元素如下:

           <name>——用於指定屬性名稱

           <required>——用於聲明該屬性是否爲必需的,本例中聲明colorloop 兩個屬性都不是必需的。

 -->

<taglib>

    <tlibversion>1.0</tlibversion>

    <jspversion>1.1</jspversion>

    <shortname>test</shortname><!-- 標籤以<myhr:XXX />形式 -->

    <tag>

       <name>bodytag</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.TestBodyTag</tagclass>

       <bodycontent>tagdependent</bodycontent>

       <attribute>

           <name>loop</name>

           <required>true</required>

       </attribute>

    </tag>

</taglib>

 

 

 

步驟三:在JSP 中使用該標記

<%@ page language="java"   pageEncoding="UTF-8"%>

<%@ taglib prefix="test" uri="/WEB-INF/test-tld/testbodytag.tld" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>測試自定義帶標籤體的標籤</title>

  </head>

  <body>

        測試帶標記體的自定義標記:<br>

        <test:bodytag loop="4">

           這是標記體<br />

        </test:bodytag>

  </body>

</html>

 

運行圖:

 

 

 

 

5.3 一個簡單的帶標記體的標籤(二)

在doStartTag()方法中返回EVAL_BODY_INCLUDE,簡單地將標記體的內容直接輸出到了瀏覽器中,並未對內容進行任何處理,在一些業務中有時需要對標記體正文進行處理,以下示例演示瞭如何讀取標記體內容並進行處理:

   

步驟一:編寫標記處理類

package tag;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.tagext.BodyContent;

import javax.servlet.jsp.tagext.BodyTagSupport;

 

/*

 * doStratTag()中的返回值EVAL_BODY_BUFFERED 代表不直接將標記體內容寫到輸出流中,

 而是緩存到成員變量bodyContent 中(該成員從BodyTagSupport 繼承過來),

 * EVAL_BODY_INCLUDE是直接將標記體內容寫到輸出流中

 * */

 

publicclass EqualTag extends BodyTagSupport{

 

    private String name = "";

    private String value = "";

    publicvoid setName(String name) {

       this.name = name;

    }

 

    publicvoid setValue(String value) {

       this.value = value;

    }

 

    publicint doStartTag() throws JspException {

       System.out.println("do starttag()....");

       returnEVAL_BODY_BUFFERED;  //不直接將標記體內容寫到輸出流中,而是緩存到成員變量bodyContent 

    }  

 

    publicvoid setBodyContent(BodyContent b) {

       System.out.println("setBodycontent()...."+b.getString()+"++");

       this.bodyContent = b;  //bodyContent 賦值前,bodyContent是空的

       System.out.println("setBodycontent()...."+bodyContent.getString()+"++");

    }

 

    //初始化標記體

    publicvoid doInitBody() throws JspException {

       System.out.println("doInitBody()....."+bodyContent.getString()+"++");

    }

   

    publicint doAfterBody() throws JspException {

       System.out.println("doAfterBody()...."+bodyContent.getString()+"++");

       returnSKIP_BODY;  //停止包含

    }

 

    publicint doEndTag() throws JspException {  //處理標籤體內容,將標籤體的內容加租傾斜

       System.out.println("doEndTag()..."+bodyContent.getString()+"++");

       String username = (String)pageContext.getSession().getAttribute(name);  //獲得存在session的某屬性的值,該屬性值由標籤屬性提供獲取。

       String str = bodyContent.getString();

      

       if(username.equals(value)){  //如果該值與標籤屬性相等

           str = "<b><i>"+str+"</i></b>";   //加粗傾斜,不是的話就原樣輸出

       }

      

       try {

           JspWriter out = pageContext.getOut();

           out.print(str);  //將加粗傾斜後的標籤體輸出到頁面上

           this.bodyContent = null;

       catch (Exception e) {

           e.printStackTrace();

       }

   

       returnEVAL_PAGE;

    }

}

 

 

 

步驟二:在標記庫描述符文件testbodytag.tld,添加tag標記:

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

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">    

<!--

解釋:

    tld 文件中,映射了標記名和處理程序類;

    <tallib>元素,代表開始一個標記庫的描述

    <tligversion>元素,代表標記庫的版本

    <jspversion>元素,代表標記所支持的JSP 的版本

    <shortname>爲標記庫起別名,相當於註釋,無實際用途

    <tag>元素,代表開始描述一個標記,其下子元素如下:

    <name>——爲標記處理類起的標記名

    <tagclass>——指定標記處理類的全名(即帶包的名字)

    <bodycontent>——標記體的類型,該示例中不需要標記體,所有設置爲EMPTY,該值的其他取值在後續內容中講解

    <tag>中的子元素

       <attribute>用於爲標籤聲明屬性,其子元素如下:

           <name>——用於指定屬性名稱

           <required>——用於聲明該屬性是否爲必需的,本例中聲明colorloop 兩個屬性都不是必需的。

 -->

<taglib>

    <tlibversion>1.0</tlibversion>

    <jspversion>1.1</jspversion>

    <shortname>test</shortname><!-- 標籤以<myhr:XXX />形式 -->

    <tag>

       <name>bodytag</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.TestBodyTag</tagclass>

       <bodycontent>tagdependent</bodycontent>

       <attribute>

           <name>loop</name>

           <required>true</required>

       </attribute>

    </tag>

    <tag>

       <name>equal</name>

       <tagclass>tag.EqualTag</tagclass>

       <bodycontent>tagdependent</bodycontent>

       <attribute>

           <name>name</name>

           <required>true</required>

       </attribute>

       <attribute>

           <name>value</name>

           <required>true</required>

       </attribute>

    </tag>

</taglib>

 

 

步驟三:在JSP 中使用該標記

<%@ page language="java"   pageEncoding="UTF-8"%>

<%@ taglib prefix="test" uri="/WEB-INF/test-tld/testbodytag.tld" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>測試自定義帶標籤體的標籤</title>

  </head>

  <body>

    <% session.setAttribute("username","tom"); %>

    <test:equal name="username" value="tom">session中的username的屬性值如果是tom,則這段文字加粗傾斜</test:equal>

    <br />

    <test:equal name="username" value="tom1">session中的username的屬性值如果是tom,則這段文字加粗傾斜</test:equal>

  </body>

</html>

 

 

運行界面如下:

 

 

 

後臺輸出如下:

do starttag()....

setBodycontent()....++

setBodycontent()....++

doInitBody().....++

doAfterBody()....session中的username的屬性值如果是tom,則這段文字加粗傾斜++

doEndTag()...session中的username的屬性值如果是tom,則這段文字加粗傾斜++

do starttag()....

setBodycontent()....++

setBodycontent()....++

doInitBody().....++

doAfterBody()....session中的username的屬性值如果是tom,則這段文字加粗傾斜++

doEndTag()...session中的username的屬性值如果是tom,則這段文字加粗傾斜++

 

 

 

另外,附上各標籤的方法的返回值綜述:

 

 

 

 

六、標籤中的子標記

一個標籤中可以再包含其他的子標記,這種標籤稱爲嵌套標記。創建嵌套標籤時,標記處理類與普通標籤相似,但在doStartTag()方法中必須返回EVAL_BODY_INCLUDE,JSP 容器纔會處理嵌套的子標記。

 

         步驟一:編寫頂級標記處理類

package tag;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.BodyTagSupport;

 

publicclass NestTag extends BodyTagSupport{

    private String name = "";

    private String value = "";

    publicvoid setName(String name) {

       this.name = name;

    }

 

    publicvoid setValue(String value) {

       this.value = value;

    }

 

    publicint doStartTag() throws JspException {

       String username = (String)pageContext.getSession().getAttribute(name);

       if(username.equals(value)){

           returnEVAL_BODY_INCLUDE//自動將標籤體包含到輸出流(因爲頂級標籤的標籤體是一子標籤,還要進行該子標籤的標籤處理)

       }else{

           returnSKIP_BODY//跳過標籤體,不處理

       }

    }

 

   

}

 

步驟二:在標記庫描述符文件testbodytag.tld,添加tag標記:

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

<!DOCTYPE taglib

        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">    

<!--

解釋:

    tld 文件中,映射了標記名和處理程序類;

    <tallib>元素,代表開始一個標記庫的描述

    <tligversion>元素,代表標記庫的版本

    <jspversion>元素,代表標記所支持的JSP 的版本

    <shortname>爲標記庫起別名,相當於註釋,無實際用途

    <tag>元素,代表開始描述一個標記,其下子元素如下:

    <name>——爲標記處理類起的標記名

    <tagclass>——指定標記處理類的全名(即帶包的名字)

    <bodycontent>——標記體的類型,該示例中不需要標記體,所有設置爲EMPTY,該值的其他取值在後續內容中講解

    <tag>中的子元素

       <attribute>用於爲標籤聲明屬性,其子元素如下:

           <name>——用於指定屬性名稱

           <required>——用於聲明該屬性是否爲必需的,本例中聲明colorloop 兩個屬性都不是必需的。

 -->

<taglib>

    <tlibversion>1.0</tlibversion>

    <jspversion>1.1</jspversion>

    <shortname>test</shortname><!-- 標籤以<myhr:XXX />形式 -->

    <tag>

       <name>bodytag</name><!-- 該標籤爲<myhr:MyHr /> -->

       <tagclass>tag.TestBodyTag</tagclass>

       <bodycontent>tagdependent</bodycontent>

       <attribute>

           <name>loop</name>

           <required>true</required>

       </attribute>

    </tag>

    <tag>

       <name>equal</name>

       <tagclass>tag.EqualTag</tagclass>

       <bodycontent>tagdependent</bodycontent>

       <attribute>

           <name>name</name>

           <required>true</required>

       </attribute>

       <attribute>

           <name>value</name>

           <required>true</required>

       </attribute>

    </tag>

    <tag>

       <name>nest</name>

       <tagclass>tag.NestTag</tagclass>

       <bodycontent>JSP</bodycontent>  <!-- 該聲明標記體是其他標記,也可以是Jsp標準標記 -->

       <attribute>

           <name>name</name>

           <required>true</required>

       </attribute>

       <attribute>

           <name>value</name>

           <required>true</required>

       </attribute>

    </tag>

</taglib>

 

 

步驟三:在JSP 中使用該標記

<%@ page language="java"   pageEncoding="UTF-8"%>

<%@ taglib prefix="test" uri="/WEB-INF/test-tld/testbodytag.tld" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>測試嵌套的標籤</title>

  </head>

  <body>

    <% session.setAttribute("username","tom"); %>

     

    <test:nest name="username" value="tom">

        <test:bodytag loop="3">

           session中的用戶名是tom<br/>

        </test:bodytag>

    </test:nest>

  </body>

</html>

 

運行界面如下:

 

 

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