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 個,被分為了四類,分別是:
- 多用途核心標籤: <c:out> 、 <c:set> 、 <c:remove> 、 <c:catch> 。
- 條件控制標籤: <c:if> 、 <c:choose> 、 <c:when> 、 <c:otherwise> 。
- 迴圈控制標籤: <c:forEach> 、 <c:forTokens> 。
- 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 時會主動更換特殊字元,比如“ <,>,& ”(可選,預設為 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 ”的條件語句。
- <c:choose> 標籤沒有屬性,可以被認為是父標籤, <c:when> 、 <c:otherwise> 將作為其子標籤來使用。
- <c:when> 標籤等價於“ if ”語句,它包含一個 test 屬性,該屬性表示需要判斷的條件。
- <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 型別的字串,因此編碼還算比較簡單。可