概述

本教學將概述如何建立 Jakarta-Taglibs 函式庫中一些基本標籤。標籤庫可讓您建立自訂動作並封裝功能。自訂標籤可清楚地將簡報層與商業邏輯分開。它們易於維護,可重複使用的元件,可存取 JSP 頁面中所有可用的物件。請參閱 JavaServer Pages 規格,版本 1.2 以取得更多詳細資料。

實作 JSP,v1.1+ 的伺服器支援標籤庫。您可以在 JavaServer Pages 產業動態 頁面中找到各種伺服器及其目前支援的說明。Sun 網站上也有非常好的 Java Web 服務教學,其中包含 自訂標籤JSP 標準標籤庫 (JSTL) 的章節。

    標籤處理器

    執行 JSP 頁面期間協助評估動作的伺服器端物件

    標籤庫描述

    定義標籤名稱和標籤屬性的 xml 檔案

    JSP

    標籤庫可透過 taglib 指令提供給 JSP 頁面

    安裝和部署

    如何安裝現有的標籤庫

    範例

    程式碼說明

標籤處理器

標籤處理器負責 JSP 頁面與其他伺服器端物件之間的互動。當遇到自訂標籤時,會在執行 JSP 頁面期間呼叫處理器。當分別遇到自訂標籤的開始和結束標籤時,會呼叫 doStartTag()doEndTag() 方法。 release() 方法會釋放標籤處理器配置的資源。

有兩個介面描述標籤處理器

標籤 用於對不感興趣於操作其主體內容的簡單標籤處理器
BodyTag Tag 的延伸,並讓處理器存取其主體

標籤處理器有兩個主要動作方法

doStartTag()

處理此動作的起始標籤。

doEndTag() 處理此動作的結束標籤。在從 doStartTag 回傳後呼叫。
release() 釋放資源

doStartTag() 回傳下列內容

  • EVAL_BODY_INCLUDE
    • 處理動作的主體,但不要建立新的 BodyContent。傳遞主體而不加以操作。只有在您沒有實作 BodyTag 介面時才有效。
  • EVAL_BODY_TAG
    • 處理動作的主體,並建立新的 BodyContent。只有在您實作 BodyTag 介面時才有效。
  • SKIP_BODY
    • 不要評估標籤的主體

doEndTag() 回傳下列內容

  • EVAL_PAGE
    • 將評估 JSP 頁面的其餘部分
  • SKIP_PAGE
    • 將不會評估 JSP 頁面的其餘部分

回傳值指示 JSP 容器如何評估 JSP 頁面的其餘部分。release() 方法釋放標籤處理器配置的資源。

TagSupportBodyTagSupportTag 的子類別,可用於在建立新的標籤處理器時作為基礎類別。

TagSupport 類別是一個實作 Tag 介面並新增其他便利方法的公用程式類別,包括

如果標籤處理器操作動作的主體,則必須實作 BodyTag 介面。doStartTag() 必須回傳 EVAL_BODY_TAG,才能評估標籤的主體。如果回傳 SKIP_BODY,則會忽略主體。與主體內容互動的方法包括

doInitBody() 在評估標籤的主體之前,但在設定主體內容之後呼叫
doAfterBody() 在評估主體內容之後呼叫

BodyTagSupport 類別實作 BodyTag 介面並新增其他便利方法。這些方法包括

在 Web 應用程式中,處理器必須存在於下列標準 Java 類別位置之一

標籤處理器可以存取 JSP 容器使用設定器方法設定的一些屬性。這包括 pageContextparent 物件。標籤處理器也可以存取伺服器端物件和封裝動作。如果標籤是巢狀的,可以使用下列任一方式存取封裝標籤的父處理器

取得父物件後,就可以取得父處理器的靜態和動態建立的物件。

標籤庫描述檔

JSP 容器使用標籤庫描述檔 (TLD) 來詮釋包含標籤庫指令頁面,這些指令會參照該標籤庫。它是一個 XML 文件,會將動作標籤對應到標籤處理器類別。您可以使用兩種方式來尋找 TLD

您可以在 Servlet 2.2 和 JSP 1.1 規格中找到有關 web.xml taglib 元素的更多資訊。

由於最近變更為呼叫驗證剖析器,因此您需要明確參照外部 DOCTYPE

                                        
  <!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 taglib 元素是文件根目錄。它具有下列子元素

tlibversion 標籤庫實作的版本
jspversion 標籤庫需要的 JSP 規格版本
shortname 可從 JSP 頁面參照標籤庫的名稱
uri 唯一識別標籤庫的 URI - 描述標籤庫「用途」的資訊字串
info 描述標籤庫「用途」的字串

tag 元素定義標籤庫中的動作。它可能有幾個定義動作的子元素

name 唯一的動作名稱
tagclass 實作 javax.servlet.jsp.tagext.Tag 的標籤處理器類別
teiclass javax.servlet.jsp.tagext.TagExtraInfo 的可選子類別
bodycontent

三種類型的主體內容之一

info

可選的標籤特定資訊

attribute

動作的所有屬性

如果標籤有主體,則包含 bodycontent。它由頁面組成工具使用,因此不會影響主體的組成。它可以是下列三種類型之一

  • JSP(預設)
    • JSP 容器應評估標籤的任何主體,但它也可以是空的
  • tagdependent
    • 標籤的任何主體都將由標籤本身處理,但它也可以是空的
  • empty
    • 主體必須是空的

teiclass 定義腳本變數,並包含下列資訊

  • name
  • 類型
  • 變數是否需要建立
  • 範圍

attributes 可以有下列欄位

  • name(必要)
    • 屬性名稱
  • 必要
    • 屬性是否必要或選用
  • rtexprvalue
    • 如果屬性值可能在執行階段由小程式動態計算。注意:預設值為「false」,表示屬性具有靜態值。如果屬性值在要求時間決定,請務必將其設定為「true」。

對於每個屬性,您都必須在標籤處理常式中具備 JavaBeans 樣式的取得和設定方法。如果您的屬性名稱為 idTagSupport 類別會為您定義 setId() 和 getId() 方法。

JavaServer Pages

JavaServer Pages 可以處理封裝在標籤庫動作中的 XML 內容。

  <%@ taglib uri="identifier" prefix="prefix" %>

若要使用標籤庫,您需要使用 taglib 指令告訴 JSP 容器其位置。該指令必須在任何動作之前

安裝和部署

a) 建立通用標籤庫

若要安裝標籤庫,您需要執行下列步驟

  1. 將標籤類別組合在 jar 檔案中。請務必包含位於 /WEB-INF 目錄中的標籤庫 {library}.tld 檔案
  2. 將標籤 {library}.jar 檔案新增至 CLASSPATH
  3. {library}.jar 檔案複製至 /WEB-INF/lib 目錄
  4. /WEB-INF/web.xml 檔案中定義標籤庫元素。例如
      <taglib>
        <taglib-uri>http://jakarta.apache.org/taglibs/{library}</taglib-uri>
        <taglib-location>/WEB-INF/{library}.tld</taglib-location>
      </taglib>
        
  5. 在 jsp 頁面中定義標籤擴充。 <taglib-uri>uri 指令必須相符。 prefix 識別 jsp 頁面中標籤庫中的標籤。例如
  6.   <%@ taglib uri="http://jakarta.apache.org/taglibs/{library}" prefix="x" %>
        

b) 新增 Jakarta-Taglibs 庫

若要將標籤庫子專案新增至 Jakarta-Taglibs,您需要執行下列動作

  1. 建立專案的頂層目錄。
  2. 從現有子專案中複製下列頂層檔案
    • build.sh
    • build.bat
    • build.xml
  3. taglib.name 屬性變更為新的自訂標籤庫子專案名稱
  4. 複製現有子專案的目錄結構
  5. 修改頂層 Jakarta-Taglibs build.xml 檔案以納入新的庫

c) 部署標籤庫

使用 jakarta-taglibs 專案中的建置指令碼建立 war 檔案。建置 war 檔案後,您可以將該檔案放置在 $TOMCAT_HOME/webapps 目錄中。Tomcat 會載入您的類別並建立新的內容。

war 檔案應具有下列結構

  META-INF/
  META-INF/MANIFEST.MF
  WEB-INF/
  WEB-INF/classes/
  WEB-INF/lib/
  WEB-INF/lib/{tagLibrary}.jar
  WEB-INF/web.xml
  WEB-INF/{tagLibrary}.tld

如果您不想使用 jar 檔案,您可以將所有類別檔案放置在 /WEB-INF/classes 目錄中。

請參閱 Java Servlet 規範,v2.2 以取得有關 war 檔案的更多資訊。

範例

一些範例包括

基本標籤

這個基本標籤是「Hello World」範例。每當遇到標籤時,就會列印「Hello World」文字。

Hello World 標籤處理常式

您可以在 /WEB-INF/classes/basic 目錄中找到 Hello World 標籤的標籤處理常式,因為它是 basic 套件的一部分

  package basic;

匯入 jsp 和標籤類別

  import javax.servlet.jsp.*;
  import javax.servlet.jsp.tagext.*;

Hello World 標籤處理常式實作 doStartTag() 方法,在遇到開始標籤時會呼叫該方法。

    public int doStartTag() throws JspException {
        try {
            pageContext.getOut().print("Hello World");
        } catch (Exception ex) {
            throw new JspException("IO problems");
        }
        return SKIP_BODY;
    }

JSP 容器設定 pageContext,且標籤處理常式可以使用。 SKIP_BODY 值可確保不會評估標籤主體。

Hello World 標籤庫描述符

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

描述部署描述符 DOCTYPE 的 XML 標頭。部署描述符包含 Web 應用程式的元素和組態資訊。

  <!DOCTYPE taglib
            PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" 
            "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">

初始標籤庫描述

  <taglib>
    <!-- The version number of this tag library -->
    <tlibversion>1.0</tlibversion>

    <!-- The JSP specification version required to function -->
    <jspversion>1.1</jspversion>

    <!-- The short name of this tag library -->
    <shortname>utility</shortname>

    <!-- Public URI that uniquely identifies this version of the tag library -->
    <uri>http://jakarta.apache.org/taglibs/utilitytags</uri>

    <!-- General information about this tag library -->
    <info>
          A simple tag library for the examples
    </info>

Hello World 標籤描述。

  • tagclass 元素將 Hello World 標籤處理常式與 Hello World 標籤關聯
  • bodycontent 標籤告訴我們該標籤不會包含任何主體
  <!-- Hello tag -->
    <tag>
      <name>Hello</name>
      <tagclass>basic.Hello</tagclass>
      <bodycontent>empty</bodycontent>
      <info>
        Print Hello World
      </info>
    </tag>

web.xml 檔案

web.xml 檔案描述標籤庫描述符的標籤 uri 和位置之間的對應。

這裡的唯一 taglib-uri "http://jakarta.apache.org/taglibs/utilitytags" 與 /WEB-INF/tld/utilitytags.tld 中的標籤庫描述符關聯。

  <web-app>
    <taglib>
       <taglib-uri>
         http://jakarta.apache.org/taglibs/utilitytags
       </taglib-uri>
       <taglib-location>
         /WEB-INF/tld/utilitytags.tld
       </taglib-location>
    </taglib>
  </web-app>

Hello World jsp

以下指令告訴 JSP 容器使用在 web.xml 中定義的 "http://jakarta.apache.org/taglibs/utilitytags" uri。"jLib" 被定義為標籤的前置詞值。

  <%@ taglib uri="http://jakarta.apache.org/taglibs/utilitytags" prefix="jLib" %>

Hello World 標籤被呼叫。標籤名稱 "Hello" 在標籤庫描述符中定義。

  <jLib:Hello/>

簡單的巢狀動作

這個巢狀標籤是 "If" 條件標籤的範例。包含的指令碼會根據屬性的值進行評估或略過。

If 標籤處理常式

BodyTagSupport 類別實作 BodyTag 介面,並有 bodyContent 屬性的 getter 方法。

  public class IfTag extends BodyTagSupport {

doStartTag() 方法會在遇到開始標籤時呼叫,並呼叫本地的 getPredicate() 方法。如果傳回值為 true,則會評估標籤主體的其餘部分,否則會略過。

  public int doStartTag() {
    if (getPredicate()) return EVAL_BODY_TAG;
    else return SKIP_BODY;
  }

doAfterBody() 會在評估某些主體之後呼叫。它不會在空標籤或在 doStartTag() 中傳回 SKIP_BODY 的標籤中呼叫。

  public int doAfterBody() throws JspException {
    try {
      bodyContent.writeOut(bodyContent.getEnclosingWriter());
      return SKIP_BODY;
    } catch (IOException ex) {
      throw new JspTagException(ex.toString());
    }
  }

If 標籤庫描述符

  <!-- IF tag -->
    <tag>
      <name>If</name>
      <tagclass>lang.IfTag</tagclass>

If 標籤有一個必要的屬性。由於 rtexprvalue 設為 true,因此屬性可以有指令碼表達式作為值。該值可以在請求時動態計算。

      <attribute>
        <name>predicate</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
      </attribute>
      <info>
        Conditional Tag.
      </info>
    </tag>  

web.xml 檔案

web.xml 檔案描述標籤庫描述符的標籤 uri 和位置之間的對應。

這裡的唯一 taglib-uri "http://jakarta.apache.org/taglibs/utilitytags" 與 /WEB-INF/tld/utilitytags.tld 中的標籤庫描述符關聯。

If JSP

If 標籤需要一個屬性。predicate 屬性包含一個指令碼,它會在執行階段評估。根據 predicate 屬性的值,jLib:Hello 標籤會被評估或略過。

  <jlib:if predicate="<%= x==5 %>">
    <jLib:Hello/>   
  </jlib:if>

UtilityTags 標籤庫的文件

1. 簡介

utilitytags 自訂標籤庫包含一些基本標籤的範例。它說明了幾個直接的自訂標籤庫程式碼技巧。

2. 先決軟體

這個自訂標籤庫不需要任何軟體,只要支援 JavaServer Pages 規格版本 1.1 的 servlet 容器即可。

3. 組態資訊

請遵循下列步驟,使用這個標籤庫組態您的網路應用程式

  • 將標籤庫描述符檔案 (utilitytags/utilitytags.tld) 複製到網路應用程式的 /WEB-INF 子目錄。
  • 將標籤庫 JAR 檔案 (utilitytags/utilitytags.jar) 複製到網路應用程式的 /WEB-INF/lib 子目錄。
  • /WEB-INF/web.xml 中,將 <taglib> 元素新增到網路應用程式部署描述符,如下所示
        <taglib>
            <taglib-uri>http://jakarta.apache.org/taglibs/utilitytags</taglib-uri>
            <taglib-location>/WEB-INF/utilitytags.tld</taglib-location>
        </taglib>
        

若要在 JSP 頁面中使用這個庫中的標籤,請在每個頁面的頂端新增以下指令

    <%@ taglib uri="http://jakarta.apache.org/taglibs/utilitytags" prefix="x" %>
其中 "x" 是您希望用於這個庫中的標籤的前置詞名稱。您可以將這個值變更為您喜歡的任何前置詞。

4. 標籤文件

utilitytags 標籤庫包含下列標籤

Hello 標籤

Hello 標籤會列印出文字「Hello World」。它沒有任何屬性。

屬性
說明
必要
-
-
-
  • 複製標籤

    MacroCopy 標籤會將屬性文字複製到 Writer。

    屬性
    說明
    必要
    name
    與要複製文字相關聯的名稱。任何字串值。
  • 貼上標籤

    MacroPaste 標籤會貼上 Writer 指定的文字。

    屬性
    說明
    必要
    name
    與要貼上的文字相關聯的名稱。任何字串值。
  • 顯示來源標籤

    ShowSource 標籤會取得 jspFile 並將內容複製到 Writer。

    屬性
    說明
    必要
    jspFile
    jsp 檔案的檔名和相對路徑。任何字串值。
  • 包含標籤

    Include 標籤會包含指定 URL 的輸出。

    屬性
    說明
    必要
    url
    任何有效的 URL。
  • 如果標籤

    If 標籤是基本條件標籤。

    屬性
    說明
    必要
    謂詞
    任何字串值。
  • 迴圈標籤

    For 標籤是基本迴圈標籤。

    屬性
    說明
    必要
    反覆運算
    要完成的迴圈反覆運算次數。任何字串整數值。
    變數名稱
    與 For 迴圈相關聯的變數名稱。任何字串值。
    開始
    迴圈開始值。任何字串整數值。
  • useBean 標籤

    useBean 標籤會將 Java 物件實例與指定的 ID 相關聯。

    屬性
    說明
    必要
    id
    對 JSP 容器和頁面唯一識別 bean。任何字串值。
    範圍
    page|request|session|application
    類別名稱
    定義物件實作的類別名稱。
    類型
    定義的指令碼變數類型
    beanName
    java.beans.Beans 類別的 instantiate() 方法預期的 bean 名稱
    processRequest
    true|false。JSP 0.92 相容性。
  • 驗證標籤

    Validate 標籤會產生 Javascript 來驗證 HTML 表單。

    屬性
    說明
    必要
    name
    表單名稱。任何字串值。
    方法
    要產生的 Javascript 函式名稱。任何字串值。
    reqdFields
    以逗號分隔的強制性欄位清單。任何字串值。