1. 程式人生 > >jstl標籤庫基礎教程及其使用程式碼

jstl標籤庫基礎教程及其使用程式碼

概述

在 JSP 頁面中,使用標籤庫代替傳統的 Java 片段語言來實現頁面的顯示邏輯已經不是新技術了,然而,由自定義標籤很容易造成重複定義和非標準的實現。鑑於此,出現了 JSTL ( JSP Standard Tag Library )。大多數 JSP 頁面邏輯提供了實現的 JSTL 技術,該技術本身就是一個標籤庫。

Sun 公司 Java 規範標準的 JSTL 由 apache jakarta 組織負責維護。作為開源的標準技術,它一直在不斷地完善。 JSTL 的釋出包有兩個版本: Standard-1.0 Taglib 、 Standard-1.1 Taglib ,它們在使用時是不同的。

         Standard-1.0 Taglib ( JSTL1.0 )支援 Servlet2.3 和 JSP1.2 規範, Web 應用伺服器 Tomcat4 支援這些規範,而它的釋出也在 Tomcat 4.1.24 測試通過了。

         Standard-1.1 Taglib ( JSTL1.1 )支援 Servlet2.4 和 JSP2.0 規範, Web 應用伺服器 Tomcat5 支援這些規範,它的釋出在 Tomcat 5.0.3 測試通過了。

在本章的介紹中,將以由 Sun 釋出的 Standard-1.1 Taglib 標籤庫為主,而 apache jakarta 組織釋出的開源標籤庫,可以從 http://jakarta.apache.org/taglibs/ 找到所需要的幫助。 Sun 釋出的標準 JSTL1.1 標籤庫有以下幾個標籤:

         核心標籤庫:包含 Web 應用的常見工作,比如:迴圈、表示式賦值、基本輸入輸出等。

         國際化標籤庫:用來格式化顯示資料的工作,比如:對不同區域的日期格式化等。

         資料庫標籤庫:可以做訪問資料庫的工作。

         XML 標籤庫:用來訪問 XML 檔案的工作,這是 JSTL 標籤庫的一個特點。

         函式標籤庫:用來讀取已經定義的某個函式。

此外, JSTL 還提供了 EL 表示式語言( Expression Language )來進行輔助的工作。
 

JSTL 標籤 庫由標籤庫和 EL 表示式語言兩個部分組成。 EL 在 JSTL 1.0 規範中被引入,當時用來作為 Java 表示式來工作,而該表示式必須配合 JSTL 的標籤庫才能得到需要的結果。

說明:在 JSTL 1.1 規範中, JSP2.0 容器已經能夠獨立的理解任何 EL 表示式。 EL 可以獨立出現在 JSP 頁面的任何角落。本文隨後的內容將以 JSTL 1.1 規範作為介紹的重點。

9.2.1  JSTL EL 表示式語言簡介

EL 是從 JavaScript 指令碼語言得到啟發的一種表示式語言,它借鑑了 JavaScript 多型別轉換無關性的特點。在使用 EL 從 scope 中得到引數時可以自動轉換型別,因此對於型別的限制更加寬鬆。 Web 伺服器對於 request 請求引數通常會以 String 型別來發送,在得到時使用的 Java 語言指令碼就應該是 request.getParameter(“XXX”) ,這樣的話,對於實際應用還必須進行強制型別轉換。而 EL 就將使用者從這種型別轉換的繁瑣工作脫離出來,允許使用者直接使用 EL 表示式取得的值,而不用關心它是什麼型別。

下面的示例就是一個 EL 表示式,見例 9.1 。

例 9.1 :簡單 EL 表示式

<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
    ${sampleValue + 1} <br>
  </body>
</html> 

這個示例將在 JSP 頁面顯示為“ 1 ”, EL 表示式必須以“ ${XXX} ”來表示,其中“ XXX ”部分就是具體表達式內容,“ ${} ”將這個表示式內容包含在其中作為 EL 表示式的定義。本示例可以在滿足 JSP2.0 規範的任何 Web 應用伺服器中使用。

9.2.2  EL 表示式的預設變數

一個 EL 表示式包含變數和操作符兩個內容。任何存在於 JSP 作用範圍的 JavaBean 都可以被轉化成 EL 表示式來使用,它所包含的預設變數如下:

1 .預設變數 pageScope 、 requestScope 、 sessionScope 、 applicationScope

這 4 個預設變數包含 Scope 作用範圍的引數集合,相當於被儲存在 java.util.Map 中的某個引數。下面看簡單的示例 9.2 :

例 9.2 :使用 sessionScope 變數的 EL 表示式

<%request.getSession().setAttribute("sampleValue", new Integer(10));%>

${sessionScope.sampleValue}

取得儲存在 Session 中引數的 sessionScope 變數的 EL 表示式,“ . ”是 property 訪問操作符,在這裡表示從 Session 中取得“鍵”為“ sampleValue ”的引數,並顯示出來。顯示結果為“ 10 ”。

2 .預設變數 param 、 paramValues

這兩個預設變數包含請求引數的集合, param 表明請求包含的引數為單一控制元件, paramValues 表明請求包含的引數為控制元件陣列。下面看一個簡單示例 9.3 :

例 9.3 :提交請求的頁面和接受的頁面

<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
    <form action="SampleJsp.jsp">
    <input type="text" name="sampleValue" value="10">
    <input type="text" name="sampleValue" value="11">
    <input type="text" name="sampleValue" value="12">
    <input type="text" name="sampleSingleValue" value="SingleValue">
    <input type="submit" value="Submit">
    </form>
  </body>
</html> 

在這個頁面中定義了兩組控制元件,控制元件名為“ sampleValue ”的是一套控制元件陣列,控制元件名為“ sampleSingleValue ”的是單一控制元件,通過遞交將請求引數傳送到 SampleJsp.jsp 。

<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
    ${paramValues.sampleValue[2]} <br>
    ${param.sampleSingleValue} <br>
  </body>
</html> 

這是請求轉發到的頁面,通過 EL 表示式的 paramValues 變數得到控制元件陣列中最後一個控制元件的遞交引數,通過 EL 表示式的 param 變數得到單一控制元件的遞交引數。控制元件陣列引數的 EL 表示式使用“ [] ”來指定陣列下標。本示例將顯示控制元件陣列中最後一個控制元件的值“ 12 ”和單一控制元件的值“ SingleValue ”。

3 .預設變數 header 、 headerValues

這兩個預設變數包含請求引數頭部資訊的集合, header 變量表示單一頭部資訊, headerValues 則表示陣列型的頭部資訊。

4 .預設變數 cookie

包含所有請求的 cookie 集合,集合中的每個物件對應 javax.servlet.http.Cookie 。

5 .預設變數 initParam

包含所有應用程式初始化引數的集合。

6 .預設變數 pageContext

等價於 page 環境類 javax.servlet.jsp.PageContext 的例項,用來提供訪問不同的請求引數。

11 個預設變數幾乎包含了 Web 應用的所有基本操作,若一個表示式不使用這些變數而直接使用引數名,那麼就採用就近原則。該表示式將使用最近取得的引數值。

9.2.3  EL 表示式的操作符

EL 表示式中還有許多操作符可以幫助完成各種所需的操作,之前的示例中“ . ”、“ [] ”就是其中的兩個,下面將用表 9.1 來展示所有操作符及它們各自的功能。

表 9.1  EL 表示式的操作符

操作符

功能和作用

.

訪問一個 bean 屬性或者 Map entry

[]

訪問一個數組或者連結串列元素

()

對子表示式分組,用來改變賦值順序

? :

條件語句,比如:條件 ?ifTrue:ifFalse

如果條件為真,表示式值為前者,反之為後者

+

數學運算子,加操作

-

數學運算子,減操作或者對一個值取反

*

數學運算子,乘操作

/ 或 div

數學運算子,除操作

% 或 mod

數學運算子,模操作 ( 取餘 )

== 或 eq

邏輯運算子,判斷符號左右兩端是否相等,如果相等返回 true ,否則返回 false

!= 或 ne

邏輯運算子,判斷符號左右兩端是否不相等,如果不相等返回 true ,否則返回 false

< 或 lt

邏輯運算子,判斷符號左邊是否小於右邊,如果小於返回 true ,否則返回 false

> 或 gt

邏輯運算子,判斷符號左邊是否大於右邊,如果大於返回 true ,否則返回 false

<= 或 le

邏輯運算子,判斷符號左邊是否小於或者等於右邊,如果小於或者等於返回 true ,否則返回 false

>= 或 ge

邏輯運算子,判斷符號左邊是否大於或者等於右邊,如果大於或者等於返回 true ,否則返回 false

&& 或 and

邏輯運算子,與操作賦。如果左右兩邊同為 true 返回 true ,否則返回 false

|| 或 or

邏輯運算子,或操作賦。如果左右兩邊有任何一邊為 true 返回 true ,否則返回 false

! 或 not

邏輯運算子,非操作賦。如果對 true 取運算返回 false ,否則返回 true

empty

用來對一個空變數值進行判斷 : null 、一個空 String 、空陣列、 空 Map 、沒有條目的 Collection 集合

func(args)

呼叫方法 , func 是方法名, args 是引數,可以沒有,或者有一個、多個引數 . 引數間用逗號隔開

這些操作符都是極其有用的,下面通過幾個示例來演示它們的使用方法:

例 9.4 :幾組操作符的示例

${pageScope.sampleValue + 12} <br>            // 顯示 12

${(pageScope.sampleValue + 12)/3} <br>      // 顯示 4.0

${(pageScope.sampleValue + 12) /3==4} <br>         // 顯示 true

${(pageScope.sampleValue + 12) /3>=5} <br>         // 顯示 false

<input type="text" name="sample1" value="${pageScope.sampleValue + 10}"> // 顯示值為 10 的 Text 控制元件

可以看到,對於這些示例,程式設計者完全無需管理它們的型別轉換,在表示式內部都已經處理了。有了 EL 表示式,在 JSP 頁面的程式設計變得更靈活,也更容易。

9.2.3  JSTL 標籤庫介紹   

在 JSTL1.1 中有以下這些標籤庫是被支援的: Core 標籤庫、 XML processing 標籤庫、 I18N formatting 標籤庫、 Database access 標籤庫、 Functions 標籤庫。對應的識別符號見表 9.2 所示:

表 9.2 標籤庫的識別符號

標籤庫

URI

字首

Core

http://java.sun.com/jsp/jstl/core

c

XML processing

http://java.sun.com/jsp/jstl/xml

x

I18N formatting

http://java.sun.com/jsp/jstl/fmt

fmt

Database access

http://java.sun.com/jsp/jstl/sql

sql

Functions

http://java.sun.com/jsp/jstl/functions

fn

下面看例 9.5 ,簡單使用標籤庫的示例。

例 9.5 :簡單 JSTL 標籤庫示例

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
    <c:forEach var="i" begin="1" end="10" step="1">
      ${i}
      <br />
    </c:forEach>
  </body>
</html>

在該示例的 JSP 頁面中聲明瞭將使用 Core 標籤庫,它的 URI 為“ http://java.sun.com/jsp/jstl/core ”,字首為“ c ”。之後,頁面中 <c:forEach> 標籤就是使用了 JSTL 的標籤進行了工作。對於該標籤的功能,這裡暫時不作具體講解,只是讓讀者能夠有個簡單的概念,瞭解怎樣定義和使用標籤庫。

9.3  JSTL Core 標籤庫

Core 標籤庫,又被稱為核心標籤庫,該標籤庫的工作是對於 JSP 頁面一般處理的封裝。在該標籤庫中的標籤一共有 14 個,被分為了四類,分別是:

  1. 多用途核心標籤: <c:out> 、 <c:set> 、 <c:remove> 、 <c:catch> 。
  2. 條件控制標籤: <c:if> 、 <c:choose> 、 <c:when> 、 <c:otherwise> 。
  3. 迴圈控制標籤: <c:forEach> 、 <c:forTokens> 。
  4. URL 相關標籤: <c:import> 、 <c:url> 、 <c:redirect> 、 <c:param> 。

以下是各個標籤的用途和屬性以及簡單示例。

9.3.1  用於顯示的 <c:out> 標籤

<c:out> 標籤是一個最常用的標籤,用於在 JSP 中顯示資料。它的屬性和描述如表 9.3 所示:

表 9.3   <c:out> 標籤屬性和說明

屬性

描述

value

輸出到頁面的資料,可以是 EL 表示式或常量(必須)

default

當 value 為 null 時顯示的資料(可選)

escapeXml

當設定為 true 時會主動更換特殊字元,比如“ &lt;,&gt;,&amp; ”(可選,預設為 true )

在 JSTL1.0 的時候,在頁面顯示資料必須使用 <c:out> 來進行。然而,在 JSTL1.1 中,由於 JSP2.0 規範已經預設支援了 EL 表示式 ,因此可以直接在 JSP 頁面使用表示式。下面看一個示例。

<c:out value="${sessionScope.anyValue}" default="no value" escapeXml="false"/>

該示例將從 Session 查詢名為“ anyValue ”的引數,並顯示在頁面,若沒有找到則顯示“ no value ”。

9.3.2  用於賦值的 <c:set> 標籤

<c:set> 標籤用於為變數或 JavaBean 中的變數屬性賦值的工作。它的屬性和描述如表 9.4 所示:

表 9.4   <c:set> 標籤屬性和說明

屬性

描述

value

值的資訊,可以是 EL 表示式或常量

target

被賦值的 JavaBean 例項的名稱,若存在該屬性則必須存在 property 屬性(可選)

property

JavaBean 例項的變數屬性名稱(可選)

var

被賦值的變數名(可選)

scope

變數的作用範圍,若沒有指定,預設為 page (可選)

當不存在 value 的屬性時,將以包含在標籤內的實體資料作為賦值的內容。下面看一個示例:

<c:set value="this is andy" var="oneString"/>

${oneString} <br>

該示例將為名為“ oneString ”的變數賦值為“ this is andy ”,其作用範圍為 page 。

9.3.3  用於刪除的 <c:remove> 標籤

<c:remove> 標籤用於刪除存在於 scope 中的變數。它的屬性和描述如表 9.5 所示:

表 9.5   <c:remove> 標籤屬性和說明

屬性

描述

var

需要被刪除的變數名

scope

變數的作用範圍,若沒有指定,預設為全部查詢(可選)

下面看一個示例:

<c:remove var="sampleValue" scope="session"/>

${sessionScope.sampleValue} <br>

該示例將存在於 Session 中名為“ sampleValue ”的變數刪除。下一句 EL 表示式顯示該變數時,該變數已經不存在了。

9.3.4  用於異常捕獲的 <c:catch> 標籤

<c:catch> 標籤允許在 JSP 頁面中捕捉異常。它包含一個 var 屬性,是一個描述異常的變數,改變數可選。若沒有 var 屬性的定義,那麼僅僅捕捉異常而不做任何事情,若定義了 var 屬性,則可以利用 var 所定義的異常變數進行判斷轉發到其他頁面或提示報錯資訊。看一個示例。

<c:catch var="err">

         ${param.sampleSingleValue[9] == 3}

</c:catch>

${err}

當“ ${param.sampleSingleValue[9] == 3} ”表示式有異常時,可以從 var 屬性“ err ”得到異常的內容,通常判斷“ err ”是否為 null 來決定錯誤資訊的提示。

9.3.5  用於判斷的 <c:if> 標籤

<c:if> 標籤用於簡單的條件語句。它的屬性和描述如表 9.6 所示:

表 9.6   <c:if> 標籤屬性和說明

屬性

描述

test

需要判斷的條件

var

儲存判斷結果 true 或 false 的變數名,該變數可供之後的工作使用(可選)

scope

變數的作用範圍,若沒有指定,預設為保存於 page 範圍中的變數(可選)

下面看一個示例:

<c:if test="${paramValues.sampleValue[2] == 12}" var="visits">

      It is 12

</c:if><br>

${visits} <br>

該示例將判斷 request 請求提交的傳入控制元件陣列引數中,下標為“ 2 ”的控制元件內容是否為“ 12 ”,若為 12 則顯示“ It is 12 ”。判斷結果被儲存在 page 範圍中的“ visits ”變數中。  

9.3.6  用於複雜判斷的 <c:choose> 、 <c:when> 、 <c:otherwise> 標籤

這三個標籤用於實現複雜條件判斷語句,類似“ if,elseif ”的條件語句。

  1. <c:choose> 標籤沒有屬性,可以被認為是父標籤, <c:when> 、 <c:otherwise> 將作為其子標籤來使用。
  2. <c:when> 標籤等價於“ if ”語句,它包含一個 test 屬性,該屬性表示需要判斷的條件。
  3. <c:otherwise> 標籤沒有屬性,它等價於“ else ”語句。

下面看一個複雜條件語句的示例。

<c:choose>
         <c:when test="${paramValues.sampleValue[2] == 11}">
                   not 12 not 13,it is 11
         </c:when>
         <c:when test="${paramValues.sampleValue[2] == 12}">
                   not 11 not 13,it is 12
         </c:when>
         <c:when test="${paramValues.sampleValue[2] == 13}">
                   not 11 not 12,it is 13
         </c:when>
         <c:otherwise>
                   not 11 、 12 、 13
         </c:otherwise>
</c:choose>

該示例將判斷 request 請求提交的傳入控制元件陣列引數中,下標為“ 2 ”控制元件內容是否為“ 11 ”或“ 12 ”或“ 13 ”,並根據判斷結果顯示各自的語句,若都不是則顯示“ not 11 、 12 、 13 ”。

9.3.7  用於迴圈的 <c:forEach> 標籤

<c:forEach> 為迴圈控制標籤。它的屬性和描述如表 9.7 所示:

表 9.7   <c:forEach> 標籤屬性和說明

屬性

描述

items

進行迴圈的集合(可選)

begin

開始條件(可選)

end

結束條件(可選)

step

迴圈的步長,預設為 1 (可選)

var

做迴圈的物件變數名,若存在 items 屬性,則表示迴圈集合中物件的變數名(可選)

varStatus

顯示迴圈狀態的變數(可選)

下面看一個集合迴圈的示例。

<%ArrayList arrayList = new ArrayList();

                   arrayList.add("aa");

                   arrayList.add("bb");

                   arrayList.add("cc");

%>

<%request.getSession().setAttribute("arrayList", arrayList);%>

<c:forEach items="${sessionScope.arrayList}" var="arrayListI">

         ${arrayListI}

</c:forEach>

該示例將儲存在 Session 中的名為“ arrayList ”的 ArrayList 型別集合引數中的物件依次讀取出來, items 屬性指向了 ArrayList 型別集合引數, var 屬性定義了一個新的變數來接收集合中的物件。最後直接通過 EL 表示式顯示在頁面上。下面看一個簡單迴圈的示例。

<c:forEach var="i" begin="1" end="10" step="1">

      ${i}<br />

</c:forEach>

該示例從“ 1 ”迴圈到“ 10 ”,並將迴圈中變數“ i ”顯示在頁面上。

9.3.8  用於分隔字元的 <c:forTokens> 標籤

<c:forTokens> 標籤可以根據某個分隔符分隔指定字串,相當於 java.util.StringTokenizer 類。它的屬性和描述如表 9.8 所示:

表 9.8   <c:forTokens> 標籤 屬性和說明

屬性

描述

items

進行分隔的 EL 表示式或常量

delims

分隔符

begin

開始條件(可選)

end

結束條件(可選)

step

迴圈的步長,預設為 1 (可選)

var

做迴圈的物件變數名(可選)

varStatus

顯示迴圈狀態的變數(可選)

下面看一個示例。

<c:forTokens items="aa,bb,cc,dd" begin="0" end="2" step="2" delims="," var="aValue">

         ${aValue}

</c:forTokens>

需要分隔的字串為“ aa,bb,cc,dd ”,分隔符為“ , ”。 begin 屬性 指定從第一個“ , ”開始分隔, end 屬性指定分隔到第三個“ , ”,並將做迴圈的變數名指定為“ aValue ”。由於步長為“ 2 ”,使用 EL 表示式 ${aValue} 只能顯示“ aa

9.3.9  用於包含頁面的 <c:import>

<c:import> 標籤允許包含另一個 JSP 頁面到本頁面來。它的屬性和描述如表 9.9 所示:

表 9.9   <c:import> 標籤屬性和說明

屬性

描述

url

需要匯入頁面的 URL

context

Web Context 該屬性用於在不同的 Context 下匯入頁面,當出現 context 屬性時,必須以“ / ”開頭,此時也需要 url 屬性以“ / ”開頭(可選)

charEncoding

匯入頁面的字符集(可選)

var

可以定義匯入文字的變數名(可選)

scope

匯入文字的變數名作用範圍(可選)

varReader

接受文字的 java.io.Reader 類變數名(可選)

下面看一個示例。

<c:import url="/MyHtml.html" var="thisPage" />

<c:import url="/MyHtml.html" context=”/sample2” var="thisPage"/>

<c:import url="www.sample.com/MyHtml.html" var="thisPage"/>

該示例演示了三種不同的匯入方法,第一種是在同一 Context 下的匯入,第二種是在不同的 Context 下匯入,第三種是匯入任意一個 URL 。

9.3.10  用於得到 URL 地址的 <c:url> 標籤

<c:url> 標籤用於得到一個 URL 地址。它的屬性和描述如表 9.10 所示:

表 9.10  <c:url> 標籤屬性和說明

屬性

描述

value

頁面的 URL 地址

context

Web Context 該屬性用於得到不同 Context 下的 URL 地址,當出現 context 屬性時,必須以“ / ”開頭,此時也需要 url 屬性以“ / ”開頭(可選)

charEncoding

URL 的字符集(可選)

var

儲存 URL 的變數名(可選)

scope

變數名作用範圍(可選)

下面看一個示例:

<c:url value="/MyHtml.html" var="urlPage" />

<a href="${urlPage}">link</a>

得到了一個 URL 後,以 EL 表示式放入 <a> 標籤的 href 屬性,達到連結的目的。

9.3.11  用於頁面重定向的 <c:redirect> 標籤

<c:redirect> 用於頁面的重定向,該標籤的作用相當於 response.setRedirect 方法的工作。它包含 url 和 context 兩個屬性,屬性含義和 <C:url> 標籤相同。下面看一個示例。

<c:redirect url="/MyHtml.html"/>

該示例若出現在 JSP 中,則將重定向到當前 Web Context 下的“ MyHtml.html ”頁面,一般會與 <c:if> 等標籤一起使用。

9.3.12  用於包含傳遞引數的 <c:param> 標籤

<c:param> 用來為包含或重定向的頁面傳遞引數。它的屬性和描述如表 9.11 所示:

表 9.11   <c:param> 標籤屬性和說明

屬性

描述

name

傳遞的引數名

value

傳遞的引數值(可選)

下面是一個示例:

<c:redirect url="/MyHtml.jsp">

<c:param name="userName" value=”RW” />

</c:redirect>

該示例將為重定向的“ MyHtml.jsp ”傳遞指定引數“ userName=’RW’ ”。

9.4  JSTL XML processing 標籤庫

在企業級應用越來越依賴 XML 的今天, XML 格式的資料被作為資訊交換的優先選擇。 XML processing 標籤庫為程式設計者提供了基本的對 XML 格式檔案的操作。在該標籤庫中的標籤一共有 10 個,被分為了三類,分別是:

q         XML 核心標籤: <x:parse> 、 <x:out> 、 <x:set> 。

q         XML 流控制標籤: <x:if> 、 <x:choose> 、 <x:when> 、 <x:otherwise> 、 <x:forEach> 。

q         XML 轉換標籤: <x:transform> 、 <x:param> 。

由於該組標籤庫專注於對某一特定領域的實現,因此本書將只選擇其中常見的一些標籤和屬性進行介紹。

9.4.1  用於解析 XML 檔案的 <x:parse> 標籤

<x:parse> 標籤是該組標籤庫的核心,從其標籤名就可以知道,它是作為解析 XML 檔案而存在的。它的屬性和描述如表 9.12 所示:

表 9.12   <x:parse> 標籤屬性和說明

屬性

描述

doc

源 XML 的內容,該屬性的內容應該為 String 型別或者 java.io.Reader 的例項,可以用 xml 屬性來替代,但是不被推薦

var

將解析後的 XML 儲存在該屬性所指定的變數中,之後 XML processing 標籤庫中的其他標籤若要取 XML 中的內容就可以從該變數中得到(可選)

scope

變數的作用範圍(可選)

varDom

指定儲存的變數為 org.w3c.dom.Document 介面型別(可選)

scopeDom

org.w3c.dom.Document 的介面型別變數作用範圍(可選)

systemId

定義一個 URI ,該 URI 將被使用到 XML 檔案中以接入其他資原始檔(可選)

filter

該屬性必須為 org.xml.sax.XMLFilter 類的一個例項,可以使用 EL 表示式傳入,將對 XML 檔案做過濾得到自身需要的部分(可選)

其中, var 、 scope 和 varDom 、 scopeDom 不應該同時出現,而應該被視為兩個版本來使用,二者的變數都可以被 XML processing 標籤庫的其他標籤來使用。

<x:parse> 標籤單獨使用的情況很少,一般會結合 XML processing 標籤庫中的其他標籤來一起工作。下面看一個示例。

首先給出一個簡單的 XML 檔案,將對該 XML 檔案做解析,該 XML 檔名為 SampleXml.xml 。

<?xml version="1.0" encoding="UTF-8"?>
<xml-body>
         <name>RW</name>
         <passWord>123456</passWord>
         <age>28</age>
         <books>
                   <book>book1</book>
                   <book>book2</book>
                   <book>book3</book>
         </books>
</xml-body>

標籤庫的工作:

<c:import var="xmlFile" url="http://localhost:8080/booksamplejstl/SampleXml.xml"/>

<x:parse var="xmlFileValue" doc="${xmlFile}"/>

9.5  I18N formatting 標籤庫

看到 I18N 就應該想到知識“國際化”, I18N formatting 標籤庫就是用於在 JSP 頁面中做國際化的動作。在該標籤庫中的標籤一共有 12 個,被分為了兩類,分別是:

         國際化核心標籤: <fmt:setLocale> 、 <fmt:bundle> 、 <fmt:setBundle> 、 <fmt:message> 、 <fmt:param> 、 <fmt:requestEncoding> 。

         格式化標籤: <fmt:timeZone> 、 <fmt:setTimeZone> 、 <fmt:formatNumber> 、 <fmt:parseNumber> 、 <fmt:formatDate> 、 <fmt:parseDate> 。

下面只選擇其中常見的一些標籤和屬性進行介紹。

9.5.1  用於設定本地化環境的 <fmt:setLocale> 標籤

<fmt:setLocale> 標籤用於設定 Locale 環境。它的屬性和描述如表 9.17 所示:

表 9.17   <fmt:setLocale> 標籤屬性和說明

屬性

描述

value

Locale 環境的指定,可以是 java.util.Locale 或 String 型別的例項

scope

Locale 環境變數的作用範圍(可選)

下面看一個示例:

<fmt:setLocale value="zh_TW"/>

表示設定本地環境為繁體中文。

9.5.2  用於資原始檔繫結的 <fmt:bundle> 、 <fmt:setBundle> 標籤

這兩組標籤用於資源配置檔案的繫結,唯一不同的是 <fmt:bundle> 標籤將資源配置檔案綁定於它標籤體中的顯示, <fmt:setBundle> 標籤則允許將資源配置檔案儲存為一個變數,在之後的工作可以根據該變數來進行。

根據 Locale 環境的不同將查詢不同字尾的資源配置檔案,這點在國際化的任何技術上都是一致的,通常來說,這兩種標籤單獨使用是沒有意義的,它們都會與 I18N formatting 標籤庫中的其他標籤配合使用。它們的屬性和描述如表 9.18 所示:

表 9.18   <fmt:bundle> 、 <fmt:setBundle> 標籤屬性和說明

屬性

描述

basename

資源配置檔案的指定,只需要指定檔名而無須副檔名,二組標籤共有的屬性

var

<fmt:setBundle> 獨有的屬性,用於儲存資源配置檔案為一個變數

scope

變數的作用範圍

下面看一個示例

<fmt:setLocale value="zh_CN"/>

<fmt:setBundle basename="applicationMessage" var="applicationBundle"/>

該示例將會查詢一個名為 applicationMessage_zh_CN.properties 的資源配置檔案,來作為顯示的 Resource 繫結。

9.5.3  用於顯示資源配置檔案資訊的 <fmt:message> 標籤

用於資訊顯示的標籤,將顯示資源配置檔案中定義的資訊。它的屬性和描述如表 9.19 所示:

表 9.19   <fmt:message> 標籤屬性和說明

屬性

描述

key

資源配置檔案的“鍵”指定

bundle

若使用 <fmt:setBundle> 儲存了資源配置檔案,該屬性就可以從儲存的資源配置檔案中進行查詢

var

將顯示資訊儲存為一個變數

scope

變數的作用範圍

下面看一個示例:

<fmt:setBundle basename="applicationMessage" var="applicationBundle"/>

<fmt:bundle basename="applicationAllMessage">

         <fmt:message key="userName" />

         <p>

         <fmt:message key="passWord" bundle="${applicationBundle}" />

</fmt:bundle>

該示例使用了兩種資源配置檔案的繫結的做法,“ applicationMessage ”資源配置檔案利用 <fmt:setBundle> 標籤被賦於了變數“ applicationBundle ”,而作為 <fmt:bundle> 標籤定義的“ applicationAllMessage ”資源配置檔案作用於其標籤體內的顯示。

         第一個 <fmt:message> 標籤將使用“ applicationAllMessage ”資源配置檔案中“鍵”為“ userName ”的資訊顯示。

         第二個 <fmt:message> 標籤雖然被定義在 <fmt:bundle> 標籤體內,但是它使用了 bundle 屬性,因此將指定之前由 <fmt:setBundle> 標籤儲存的“ applicationMessage ”資源配置檔案,該“鍵”為“ passWord ”的資訊顯示。

9.5.4  用於引數傳遞的 <fmt:param> 標籤

<fmt:param> 標籤應該位於 <fmt:message> 標籤內,將為該訊息標籤提供引數值。它只有一個屬性 value 。

<fmt:param> 標籤有兩種使用版本,一種是直接將引數值寫在 value 屬性中,另一種是將引數值寫在標籤體內。

9.5.6  用於為請求設定字元編碼的 <fmt:requestEncoding> 標籤

<fmt:requestEncoding> 標籤用於為請求設定字元編碼。它只有一個屬性 value ,在該屬性中可以定義字元編碼。

9.5.7  用於設定時區的 <fmt:timeZone> 、 <fmt:setTimeZone> 標籤

這兩組標籤都用於設定一個時區。唯一不同的是 <fmt:timeZone> 標籤將使得在其標籤體內的工作可以使用該時區設定, <fmt:setBundle> 標籤則允許將時區設定儲存為一個變數,在之後的工作可以根據該變數來進行。它們的屬性和描述如表 9.20 所示:

表 9.20   <fmt:timeZone> 、 <fmt:setTimeZone> 標籤 屬性和說明

屬性

描述

value

時區的設定

var

<fmt:setTimeZone> 獨有的屬性,用於儲存時區為一個變數

scope

變數的作用範圍

9.5.8  用於格式化數字的 <fmt:formatNumber> 標籤

<fmt: formatNumber > 標 籤用於格式化數字。它的屬性和描述如表 9.21 所示:

表 9.21   <fmt:formatNumber> 標籤屬性和說明

屬性

描述

value

格式化的數字,該數值可以是 String 型別或 java.lang.Number 型別的例項

type

格式化的型別

pattern

格式化模式

var

結果儲存變數

scope

變數的作用範圍

maxIntegerDigits

指定格式化結果的最大值

minIntegerDigits

指定格式化結果的最小值

maxFractionDigits

指定格式化結果的最大值,帶小數

minFractionDigits

指定格式化結果的最小值,帶小數

<fmt:formatNumber> 標籤實際是對應 java.util.NumberFormat 類, type 屬性的可能值包括 currency (貨幣)、 number (數字)和 percent (百分比)。

下面看一個示例。

<fmt:formatNumber value="1000.888" type="currency" var="money"/>

該結果將被儲存在“ money ”變數中,將根據 Locale 環境顯示當地的貨幣格式。

9.5.9  用於解析數字的 <fmt:parseNumber> 標籤

<fmt:parseNumber> 標籤用於解析一個數字,並將結果作為 java.lang.Number 類的例項返回。 <fmt:parseNumber> 標籤看起來和 <fmt:formatNumber> 標籤的作用正好相反。它的屬性和描述如表 9.22 所示:

表 9.22   <fmt:parseNumber> 標籤屬性和說明

屬性

描述

value

將被解析的字串

type

解析格式化的型別

pattern

解析格式化模式

var

結果儲存變數,型別為 java.lang.Number

scope

變數的作用範圍

parseLocale

以本地化的形式來解析字串,該屬性的內容應為 String 或 java.util.Locale 型別的例項

下面看一個示例。

<fmt:parseNumber value="15%" type="percent" var="num"/>

解析之後的結果為“ 0.15 ”。

9.5.10  用於格式化日期的 <fmt:formatDate> 標籤

<fmt:formatDate> 標籤用於格式化日期。它的屬性和描述如表 9.23 所示:

表 9.23   <fmt:formatDate> 標籤屬性和說明

屬性

描述

value

格式化的日期,該屬性的內容應該是 java.util.Date 型別的例項

type

格式化的型別

pattern

格式化模式

var

結果儲存變數

scope

變數的作用範圍

timeZone

指定格式化日期的時區

<fmt:formatDate> 標籤與 <fmt:timeZone> 、 <fmt:setTimeZone> 兩組標籤的關係密切。若沒有指定 timeZone屬性, 也可以通過 <fmt:timeZone> 、 <fmt:setTimeZone> 兩組標籤設定的時區來格式化最後的結果。

9.5.11  用於解析日期的 <fmt:parseDate> 標籤

<fmt:parseDate> 標籤用於解析一個日期,並將結果作為 java.lang.Date 型別的例項返回。 <fmt:parseDate> 標籤看起來和 <fmt:formatDate> 標籤的作用正好相反。它的屬性和描述如表 9.24 所示:

表 9.24   <fmt:parseDate> 標籤屬性和說明

屬性

描述

value

將被解析的字串

type

解析格式化的型別

pattern

解析格式化模式

var

結果儲存變數,型別為 java.lang.Date

scope

變數的作用範圍

parseLocale

以本地化的形式來解析字串,該屬性的內容為 String 或 java.util.Locale 型別的例項

timeZone

指定解析格式化日期的時區

<fmt:parseNumber> 和 <fmt:parseDate> 兩組標籤都實現解析字串為一個具體物件例項的工作,因此,這兩組解析標籤對 var 屬性的字串引數要求非常嚴格。就 JSP 頁面的表示層前段來說,處理這種解析本不屬於份內之事,因此 <fmt:parseNumber> 和 <fmt:parseDate> 兩組標籤應該儘量少用,替代工作的地方應該在伺服器端表示層的後段,比如在 Servlet 中。

9.6  Database access 標籤庫

Database access 標籤庫中的標籤用來提供在 JSP 頁面中可以與資料庫進行互動的功能,雖然它的存在對於早期純 JSP 開發的應用以及小型的開發有著意義重大的貢獻,但是對於 MVC 模型來說,它卻是違反規範的。因為與資料庫互動的工作本身就屬於業務邏輯層的工作,所以不應該在 JSP 頁面中出現,而是應該在模型層中進行。

對於 Database access 標籤庫本書不作重點介紹,只給出幾個簡單示例讓讀者略微瞭解它們的功能。

Database access 標籤庫有以下 6 組標籤來進行工作: <sql:setDataSource> 、 <sql:query> 、 <sql:update> 、 <sql:transaction> 、 <sql:setDataSource> 、 <sql:param> 、 <sql:dateParam> 。

9.6.1  用於設定資料來源的 <sql:setDataSource> 標籤

<sql:setDataSource> 標籤用於設定資料來源,下面看一個示例:

<sql:setDataSource

         var="dataSrc"

         url="jdbc:postgresql://localhost:5432/myDB"

         driver="org.postgresql.Driver"

         user="admin"

         password="1111"/>

該示例定義一個數據源並儲存在“ dataSrc ”變數內。

9.6.2  用於查詢的 <sql:query> 標籤

<sql:query> 標籤用於查詢資料庫,它標籤體內可以是一句查詢 SQL 。下面看一個示例:

<sql:query var="queryResults" dataSource="${dataSrc}">

      select * from table1

</sql:query>

該示例將返回查詢的結果到變數“ queryResults ”中,儲存的結果是 javax.servlet.jsp.jstl.sql.Result 型別的例項。要取得結果集中的資料可以使用 <c:forEach> 迴圈來進行。下面看一個示例。

<c:forEach var="row" items="${queryResults.rows}">

      <tr>

               <td>${row.userName}</td>

                   <td>${row.passWord}</td>

      </tr>

</c:forEach>

“ rows ”是 javax.servlet.jsp.jstl.sql.Result 例項的變數屬性之一,用來表示資料庫表中的“列”集合,迴圈時,通過“ ${row.XXX} ”表示式可以取得每一列的資料,“ XXX ”是表中的列名。

9.6.3  用於更新的 <sql:update> 標籤

<sql:update> 標籤用於更新資料庫,它的標籤體內可以是一句更新的 SQL 語句。其使用和 <sql:query> 標籤沒有什麼不同。

9.6.4  用於事務處理的 <sql:transaction> 標籤

<sql:transaction> 標籤用於資料庫的事務處理,在該標籤體內可以使用 <sql:update> 標籤和 <sql:query> 標籤,而 <sql:transaction> 標籤的事務管理將作用於它們之上。

<sql:transaction> 標籤對於事務處理定義了 read_committed 、 read_uncommitted 、 repeatable_read 、 serializable4 個隔離級別。

9.6.5  用於事務處理的 <sql:param> 、 <sql:dateParam> 標籤

這兩個標籤用於向 SQL 語句提供引數,就好像程式中預處理 SQL 的“ ? ”一樣。 <sql:param> 標籤傳遞除 java.util.Date 型別以外的所有相融引數, <sql:dateParam> 標籤則指定必須傳遞 java.util.Date 型別的引數。

9.7 Functions 標籤庫

稱呼 Functions 標籤庫為標籤庫,倒不如稱呼其為函式庫來得更容易理解些。因為 Functions 標籤庫並沒有提供傳統的標籤來為 JSP 頁面的工作服務,而是被用於 EL 表示式語句中。在 JSP2.0 規範下出現的 Functions 標籤庫為 EL 表示式語句提供了許多更為有用的功能。 Functions 標籤庫分為兩大類,共 16 個函式。

q         長度函式: fn:length

q         字串處理函式: fn:contains 、 fn:containsIgnoreCase 、 fn:endsWith 、 fn:escapeXml 、 fn:indexOf 、 fn:join 、 fn:replace 、 fn:split 、 fn:startsWith 、 fn:substring 、 fn:substringAfter 、 fn:substringBefore 、 fn:toLowerCase 、 fn:toUpperCase 、 fn:trim

以下是各個函式的用途和屬性以及簡單示例。

9.7.1  長度函式 fn:length 函式

長度函式 fn:length 的出現有重要的意義。在 JSTL1.0 中,有一個功能被忽略了,那就是對集合的長度取值。雖然 java.util.Collection 介面定義了 size 方法,但是該方法不是一個標準的 JavaBean 屬性方法(沒有 get,set 方法),因此,無法通過 EL 表示式“ ${collection.size} ”來輕鬆取得。

fn:length 函式正是為了解決這個問題而被設計出來的。它的引數為 input ,將計算通過該屬性傳入的物件長度。該物件應該為集合型別或 String 型別。其返回結果是一個 int 型別的值。下面看一個示例。

<%ArrayList arrayList1 = new ArrayList();

                            arrayList1.add("aa");

                            arrayList1.add("bb");

                            arrayList1.add("cc");

%>

<%request.getSession().setAttribute("arrayList1", arrayList1);%>

${fn:length(sessionScope.arrayList1)}

假設一個 ArrayList 型別的例項“ arrayList1 ”,併為其新增三個字串物件,使用 fn:length 函式後就可以取得返回結果為“ 3 ”。

9.7.2  判斷函式 fn:contains 函式

fn:contains 函式用來判斷源字串是否包含子字串。它包括 string 和 substring 兩個引數,它們都是 String 型別,分佈表示源字串和子字串。其返回結果為一個 boolean 型別的值。下面看一個示例。

${fn:contains("ABC", "a")}<br>

${fn:contains("ABC", "A")}<br>

前者返回“ false ”,後者返回“ true ”。

9.7.3 fn:containsIgnoreCase 函式

fn:containsIgnoreCase 函式與 fn:contains 函式的功能差不多,唯一的區別是 fn:containsIgnoreCase 函式對於子字串的包含比較將忽略大小寫。它與 fn:contains 函式相同,包括 string 和 substring 兩個引數,並返回一個 boolean 型別的值。下面看一個示例。

${fn:containsIgnoreCase("ABC", "a")}<br>

${fn:containsIgnoreCase("ABC", "A")}<br>

前者和後者都會返回“ true ”。

9.7.4  詞頭判斷函式 fn:startsWith 函式

fn:startsWith 函式用來判斷源字串是否符合一連串的特定詞頭。它除了包含一個 string 引數外,還包含一個 subffx 引數,表示詞頭字串,同樣是 String 型別。該函式返回一個 boolean 型別的值。下面看一個示例。

${fn:startsWith ("ABC", "ab")}<br>

${fn:startsWith ("ABC", "AB")}<br>

前者返回“ false ”,後者返回“ true ”。

9.7.5  詞尾判斷函式 fn:endsWith 函式

fn:endsWith 函式用來判斷源字串是否符合一連串的特定詞尾。它與 fn:startsWith 函式相同,包括 string 和 subffx 兩個引數,並返回一個 boolean 型別的值。下面看一個示例。

${fn:endsWith("ABC", "bc")}<br>

${fn:endsWith("ABC", "BC")}<br>

前者返回“ false ”,後者返回“ true ”。

9.7.6  字元實體轉換函式 fn:escapeXml 函式

fn:escapeXml 函式用於將所有特殊字元轉化為字元實體碼。它只包含一個 string 引數,返回一個 String 型別的值。

9.7.8  字元匹配函式 fn:indexOf 函式

fn:indexOf 函式用於取得子字串與源字串匹配的開始位置,若子字串與源字串中的內容沒有匹配成功將返回“ -1 ”。它包括 string 和 substring 兩個引數,返回結果為 int 型別。下面看一個示例。

${fn:indexOf("ABCD","aBC")}<br>

${fn:indexOf("ABCD","BC")}<br>

前者由於沒有匹配成功,所以返回 -1 ,後者匹配成功將返回位置的下標,為 1 。

9.7.9  分隔符函式 fn:join 函式

fn:join 函式允許為一個字串陣列中的每一個字串加上分隔符,並連線起來。它的引數、返回結果和描述如表 9.25 所示:

表 9.25   fn:join 函式

引數

描述

array

字串陣列。其型別必須為 String[] 型別

separator

分隔符。其型別必須為 String 型別

返回結果

返回一個 String 型別的值

下面看一個示例。

<% String[] stringArray = {"a","b","c"}; %>

<%request.getSession().setAttribute("stringArray", stringArray);%>

${fn:join(sessionScope.stringArray,";")}<br>

定義陣列並放置到 Session 中,然後通過 Session 得到該字串陣列,使用 fn:join 函式並傳入分隔符“ ; ”,得到的結果為“ a;b;c ”。

9.7.10  替換函式 fn:replace 函式

fn:replace 函式允許為源字串做替換的工作。它的引數、返回結果和描述如表 9.26 所示:

表 9.26   fn:replace 函式

引數

描述

inputString

源字串。其型別必須為 String 型別

beforeSubstring

指定被替換字串。其型別必須為 String 型別

afterSubstring

指定替換字串。其型別必須為 String 型別

返回結果

返回一個 String 型別的值

下面看一個示例。

${fn:replace("ABC","A","B")}<br>

將“ ABC ”字串替換為“ BBC ”,在“ ABC ”字串中用“ B ”替換了“ A ”。

9.7.11  分隔符轉換陣列函式 fn:split 函式

fn:split 函式用於將一組由分隔符分隔的字串轉換成字串陣列。它的引數、返回結果和描述如表 9.27 所示:

表 9.27   fn:split 函式

引數

描述

string

源字串。其型別必須為 String 型別

delimiters

指定分隔符。其型別必須為 String 型別

返回結果

返回一個 String[] 型別的值

下面看一個示例。

${fn:split("A,B,C",",")}<br>

將“ A,B,C ”字串轉換為陣列 {A,B,C} 。

9.7.12  字串擷取函式 fn:substring 函式

fn:substring 函式用於擷取字串。它的引數、返回結果和描述如表 9.28 所示:

表 9.28   fn:substring 函式

引數

描述

string

源字串。其型別必須為 String 型別

beginIndex

指定起始下標(值從 0 開始)。其型別必須為 int 型別

endIndex

指定結束下標(值從 0 開始)。其型別必須為 int 型別

返回結果

返回一個 String 型別的值

下面看一個示例。

${fn:substring("ABC","1","2")}<br>

擷取結果為“ B ”。


9.7.14  起始到定位擷取字串函式 fn:substringBefore 函式

fn:substringBefore 函式允許擷取源字元從開始到某個字串。它的引數和 fn:substringAfter 函式相同,不同的是 substring 表示的是結束字串。下面看一個示例。

${fn:substringBefore("ABCD","BC")}<br>

擷取的結果為“ A ”。

9.7.15  小寫轉換函式 fn:toLowerCase 函式

fn:toLowerCase 函式允許將源字串中的字元全部轉換成小寫字元。它只有一個表示源字串的引數 string ,函式返回一個 String 型別的值。下面看一個示例。

${fn:toLowerCase("ABCD")}<br>

轉換的結果為“ abcd ”。

9.7.16 大寫轉換函式 fn:toUpperCase 函式

fn:toUpperCase 函式允許將源字串中的字元全部轉換成大寫字元。它與 fn:toLowerCase 函式相同,也只有一個 String 引數,並返回一個 String 型別的值。下面看一個示例。

${fn:toUpperCase("abcd")}<br>

轉換的結果為“ ABCD ”。

9.7.17 空格刪除函式 fn:trim 函式

fn:trim 函式將刪除源字串中結尾部分的“空格”以產生一個新的字串。它與 fn:toLowerCase 函式相同,只有一個 String 引數,並返回一個 String 型別的值。下面看一個示例。

${fn:trim("AB C ")}D<br>

轉換的結果為“ AB CD ”,注意,它將只刪除詞尾的空格而不是全部,因此“ B ”和“ C ”之間仍然留有一個空格。

9.8 Struts 與 JSTL

9.8.1 JSTL 與 Struts 協同工作

作為伺服器端表示層 MVC 經典框架的 Struts ,其突出表現就是在表示層頁面流轉方面。雖然在顯示的檢視層, Struts 框架提供了一組功能強大的標籤庫來幫助運用。但是這組標籤庫還是比較複雜,例如要取得一個 Session 中的 JavaBean ,需要做兩個步驟的動作。

( 1 )使用 <bean:define> 標籤來定義一個目標 JavaBean 的標識,並從 Session 中取得源 JavaBean 賦給目標 JavaBean 。若該 JavaBean 本身是 String 型別,則只需要設定它的 name 屬性,否則還需要設定 property 屬性。

( 2 )使用 <bean:write> 標籤將該 JavaBean 的變數屬性顯示出來。若該 JavaBean 本身是 String 型別,則只需要設定它的 name 屬性,否則還需要設定 property 屬性。

下面看一個示例,假設 Session 中有一個引數為“ TEST ”,其值為 String 型別的字串“ hello ”。那麼使用 Struts 框架的 <bean> 標籤庫的程式碼就應該是這樣:

<bean:define id="test" name="TEST" scope="session"/>

<bean:write name="test"/>

定義一個目標 JavaBean 的標識“ test ”,然後將從 Session 中的引數“ TEST ”所取得的源 JavaBean 的例項賦給目標 JavaBean 。 <bean:write> 標籤會根據 <bean:define> 標籤的 id 屬性設定自身的 name 屬性,來獲取目標 JavaBean 並顯示出來。由於它們操作的是 String 型別的字串,因此編碼還算比較簡單。可