JSTL

JSTL

JSTL(Java server pages standarded tag library,即JSP標準標籤庫)是由JCP(Java community Proces)所制定的標準規範,它主要提供給Java Web開發人員一個標準通用的標籤庫,並由Apache的Jakarta小組來維護。開發人員可以利用這些標籤取代JSP頁面上的Java代碼,從而提高程序的可讀性,降低程序的維護難度。

使用條件


在JSP中使用JSTL標籤需要具備如下兩個條件。
條件一:要在JSP頁面中使用JSTL標籤,需使用taglib指令引用標籤庫。
條件二:要在JSP中使用JSTL標籤,還需要下載安裝JSTL實現(Implementation)。
JSTL1.2實現的下載地址為:https:jstl.dev.java.net,下載文件為jstl-impl-1.2.jar,將該文件複製到Web應用程序的WEB-INFlib文件夾中即可使用JSTL。
JSTL1.0實現的下載地址為:http://www.apache.org/dist/jakarta/taglibs/standard/,Windows用戶下載jakarta-taglibs-standard-current.zip。下載后解壓,在lib文件夾中有兩個文件:jstl.jar;standard.jar.
將這兩個文件複製到Web應用程序的WEB-INFlib文件夾中即可使用JSTL。
JSTL
JSTL
版本號JSTL 版本要求(必須滿足此條件)獲取Taglib途徑
Standard 1.2JSTL 1.2 (尚未經過JCP認證)Servlet 2.5, JavaServer Pages 2.1subversion
Standard 1.1JSTL 1.1Servlet 2.4, JavaServer Pages 2.0下載
Standard 1.0JSTL 1.0Servlet 2.3, JavaServer Pages 1.2下載

簡介


JSTL的英文全稱是JavaServer Pages Standard Tag Library,中文全稱是JSP標準標識庫。JSTL技術標準是由JCP(lava Community Process)組織的JSR052專家組發布,Apache組織將其列入Jakarta項目,Sun公司將JSTL的程序包加入網際網路服務開發工具包內(Web Services Developer Pack(WSDP)),作為JSP技術應用的一個標準。
JSTL標籤是基於JSP頁面的,這些標籤可以插入在JSP代碼中,本質上JSTL也是提前定義好的一組標籤,這些標籤封裝了不同的功能,在頁面上調用標籤時,就等於調用了封裝起來的功能。JSTL的目標是簡化JSP頁面的設計。對於頁面設計人員來說,使用腳本語言操作動態數據是比較困難的,而採用標籤和表達式語言則相對容易,JSTL的使用為頁面設計人員和程序開發人員的分工協作提供了便利。
JSTL標識庫的作用是減少JSP文件的Java代碼,使Java代碼與HTML代碼分離,所以JSTL標識庫符合MVC設計理念。MVC設計理念的優勢是將動作控制、數據處理、結果顯示三者分離。

產生背景


在JSP誕生之初,JSP提供了在HTML代碼中嵌入Java代碼的特性,這使得開發者可以利用Java語言的優勢來完成許多複雜的業務邏輯。但是,隨後開發者發現在HTML代碼中嵌入過多的Java代碼,程序員對於動輒上千行的JSP代碼基本喪失了維護能力,非常不利於JSP的維護和擴展。基於上述的這個問題,開發者嘗試著使用一種新的技術來解決上面這些問題。因此,從JSP1.1規範后,JSP增加了自定義標籤庫的支持,提供了Java腳本的復用性,提高了開發者的開發效率。
JSTL是SUN公司發布的一個針對JSP開發的新組件。JSTL允許用戶使用標籤(Tags)來進行JSP頁面開發,而不是使用傳統的JSP腳本代碼方式開發。JSTL幾乎能夠做到傳統JSP腳本代碼能做的任何事情。
JSTL
JSTL

主要組成


JSTL包含了和以下操作相關的標籤:
1、核心標籤:核心標籤庫是整個JSTL中最常用的部分,主要由以下幾部分組成:基本輸入輸出、流程式控制制、迭代操作和URL操作。負責Web應用的常見工作,如:循環、表達式賦值、基本輸入輸出等。
2、I18N格式標籤庫:用來格式化顯示數據的工作如:對不同區域的日期格式化等。
3、XML標籤庫:用來訪問XML文件的工作,支持JSP對XML文檔的處理。
4、資料庫標籤庫:SQL標籤庫包括了大部分訪問資料庫的邏輯操作,包括查詢、更新、事務處理、設置數據源等。可以做訪問資料庫的工作。
5、函數標籤庫:用來讀取已經定義的某個函數。

優點


1、在應用程序伺服器之間提供了一致的介面,最大程度地提高了WEB應用在各應用伺服器之間的移植。
2、簡化了JSP和WEB應用程序的開發。

詳細介紹


JSP 標準標籤庫(JSP Standard Tag Library,JSTL)是一個實現 Web應用程序中常見的通用功能的定製標記庫集,這些功能包括迭代和條件判斷、數據管理格式化、XML 操作以及資料庫訪問。在 developerWorks 上其新系列的第一篇文章中,軟體工程師Mark Kolb 向您展示了如何使用 JSTL 標記來避免在 JSP 頁面中使用腳本編製元素。您還將了解如何通過從表示層刪除源代碼來簡化軟體維護。最後,您將了解 JSTL 經過簡化的表達式語言,它允許在不必使用功能齊全的編程語言的情況下對 JSTL 操作指定動態屬性值。
JavaServer Pages(JSP)是用於 J2EE 平台的標準表示層技術。JSP 技術提供了用於執行計算(這些計算用來動態地生成頁面內容)的腳本編製元素和操作。腳本編製元素允許在 JSP 頁面中包括程序源代碼,在為響應用戶請求而呈現頁面時可以執行這些源代碼。操作將計算操作封裝到很象 HTML 或 XML 標記的標記中,JSP 頁面的模板文本通常包含這些標記。JSP 規範只將幾種操作定義成了標準,但從 JSP 1.1 開始,開發人員已經能夠以定製標記庫的方式創建其自己的操作了。
JSP 標準標記庫(JSTL)是 JSP 1.2 定製標記庫集,這些標記庫實現大量伺服器端 Java應用程序常用的基本功能。通過為典型表示層任務(如數據格式化和迭代或條件內容)提供標準實現,JSTL 使 JSP 作者可以專註於特定於應用程序的開發需求,而不是為這些通用操作“另起爐灶”。
當然,您可以使用 JSP 腳本編製元素(scriptlet、表達式和聲明)來實現此類任務。例如,可以使用三個 scriptlet 實現條件內容,清單 1 中著重顯示了這三個 scriptlet。但是,因為腳本編製元素依賴於在頁面中嵌入程序源代碼(通常是 Java 代碼),所以對於使用這些腳本編製元素的 JSP 頁面,其軟體維護任務的複雜度大大增加了。例如,清單 1 中的 scriptlet 示例嚴格地依賴於花括弧的正確匹配。如果不經意間引入了一個語法錯誤,則條件內容中的嵌套其它 scriptlet可能會造成嚴重破壞,並且在 JSP容器編譯該頁面時,要使所產生的錯誤信息有意義可能會很困難。
清單 1. 通過 scriptlet 實現條件內容
<% if (user.getRole() == "member")) { %>
Welcome, member!
<% } else { %>
Welcome, guest!
<% } %>
修正此類問題通常需要相當豐富的編程經驗。儘管通常會由十分精通頁面布局和圖形設計的設計人員來開發和維護 JSP,但是同一頁面中的腳本編製元素出現問題時,需要程序員的介入。這種狀況將單個文件中代碼的責任分擔給多人,因而使得開發、調試和增強此類 JSP 頁面成為很麻煩的任務。通過將常用功能包裝到定製標記庫的標準集合中,JSTL 使 JSP 作者可以減少對編製腳本元素的需求,甚至可以不需要它們,並避免了相關的維護成本。
JSTL 1.0
JSTL 1.0 發佈於 2002 年 6 月,由四個定製標記庫( core 、 format 、 xml 和 sql )和一對通用標記庫驗證器( ScriptFreeTLV 和 PermittedTaglibsTLV )組成。 core 標記庫提供了定製操作,通過限制了作用域的變數管理數據,以及執行頁面內容的迭代和條件操作。它還提供了用來生成和操作 URL 的標記。顧名思義, format 標記庫定義了用來格式化數據(尤其是數字和日期)的操作。它還支持使用本地化資源束進行 JSP 頁面的國際化。 xml 庫包含一些標記,這些標記用來操作通過 XML 表示的數據,而 sql 庫定義了用來查詢關係資料庫的操作。
兩個 JSTL 標記庫驗證器允許開發人員在其 JSP應用程序中強制使用編碼標準。可以配置 ScriptFreeTLV 驗證器以在 JSP 頁面中禁用各種類型的 JSP腳本元素― scriptlet、表達式和聲明。類似地, PermittedTaglibsTLV 驗證器可以用來限制可能由應用程序的 JSP 頁面訪問的定製標記庫集(包括 JSTL 標記庫)。
儘管 JSTL 最終將會成為 J2EE 平台的必需組件,但只有少數應用程序伺服器包括它。JSTL 1.0 的參考實現可作為 Apache軟體基金會(Apache Software Foundation)的 Jakarta Taglibs項目(請參閱 參考資料)的一部分而獲得。可以將該參考實現中的定製標記庫合併到任何支持 JSP 1.2 和 Servlet 2.3 規範的伺服器,以添加對 JSTL 的支持。
在JSTL1.0的時候,在頁面顯示數據必須用來進行,然而在JSTL1.1中,由於JSP2.0規範已經默認支持EL表達式,因此可以直接在JSP頁面使用表達式,看下面一個例子
在EL表達式尚未出現之前,Struts1中一直用輸出變數內容
表達式語言
在 JSP 1.2 中,可以使用靜態字元串或表達式(如果允許的話)指定 JSP 操作的屬性。例如,在清單 2 中,對 操作的 name 和 property 屬性指定了靜態值,而用表達式指定了其 value 屬性。這個操作的效果是將請求參數的當前值賦予命名的 bean 特性。以這種形式使用的表達式被稱為 請求時屬性值(request-time attribute value),這是構建到 JSP 規範中的用於動態指定屬性值的唯一機制。
清單 2. 合併請求時屬性值的 JSP 操作
value='<%= request.getParameter("timezone") %>'/>
因為請求時屬性值是用表達式指定的,所以它們往往有和其它腳本元素一樣的軟體維護問題。因此,JSTL 定製標記支持另一種用於指定動態屬性值的機制。可以用簡化的表達式語言(EL)而不使用完整的 JSP 表達式來指定 JSTL 操作的屬性值。EL 提供了一些標識符、存取器和運算符,用來檢索和操作駐留在 JSP容器中的數據。EL 在某種程度上以 EcmaScript(請參閱 參考資料)和 XML 路徑語言(XML Path Language,XPath)為基礎,因此頁面設計人員和程序員都應該熟悉它的語法。EL 擅長尋找對象及其特性,然後對它們執行簡單操作;它不是編程語言,甚至不是腳本編製語言。但是,與 JSTL 標記一起使用時,它就能使用簡單而又方便的符號來表示複雜的行為。EL表達式的格式是這樣的:用美元符號($)定界,內容包括在花括弧({})中,如清單 3 所示。
清單 3. 說明 EL表達式定界符的 JSTL 操作
此外,您可以將多個表達式與靜態文本組合在一起以通過字元串並置來構造動態屬性值,如清單 4 所示。單獨的表達式由標識符、存取器、文字和運算符組成。標識符用來引用存儲在數據中心中的數據對象。EL 有 11 個保留標識符,對應於 11 個 EL 隱式對象。假定所有其它標識符都引用 限制了作用域的變數。存取器用來檢索對象的特性或集合的元素。文字表示固定的值 ― 數字、字元、字元串、布爾型或空值。運算符允許對數據和文字進行組合以及比較。
清單 4. 組合靜態文本和多個 EL表達式以指定動態屬性值
限制了作用域的變數
JSP API 通過 操作允許從 JSP容器內的四個不同作用域中存儲和檢索數據。JSTL 通過提供用於指定和除去這些作用域中的對象的附加操作來擴展這一能力。此外,EL 提供將這些對象作為限制了作用域的變數進行檢索的內置支持。特別地,任何出現在 EL表達式中但不對應於任何 EL 隱式對象的標識符,都被自動假定為引用存儲在四個 JSP作用域的其中某個中的對象,這四個作用域是:
頁面作用域
請求作用域
會話作用域
應用程序作用域
您可能還記得,只有在為特定請求處理頁面期間才能檢索存儲在該頁面作用域中的對象。如果對象是存儲在請求作用域中的,可以在處理所有參與處理某請求的頁面期間檢索這些對象(譬如在對某個請求的處理中遇到了一個或多個 操作)。如果對象是存儲在會話作用域中的,則在與 Web應用程序的互動式會話期間,可以由用戶訪問的任何頁面檢索它(即,直到與該用戶交互相關聯的 HttpSession 對象無效為止)。可以由任何用戶從任何頁面訪問存儲在應用程序作用域中的對象,直到卸載 Web應用程序本身為止(通常是由於關閉 JSP容器所致)。
通過將字元串映射為期望作用域中的對象來將對象存儲到該作用域。然後,就可以通過提供相同字元串來從該作用域檢索該對象。在作用域的映射中查找字元串,並返回被映射的對象。在 Servlet API 中,將此類對象稱為相應作用域的 屬性。但是,在 EL 的上下文中,也將與屬性相關聯的字元串看作變數的名稱,該變數通過屬性映射的方式獲得特定的值。
在 EL 中,與隱式對象無關聯的標識符被認為是存儲在四個 JSP作用域中的名稱對象。首先對頁面作用域檢查是否存在這樣的標識符,其次對請求作用域、然後對會話作用域、最後對應用程序作用域依次進行這樣的檢查,然後測試該標識符的名稱是否與存儲在該作用域中的某個對象的名稱匹配。第一個這樣的匹配作為 EL標識符的值被返回。通過這種方法,可以將 EL標識符看作引用限制了作用域的變數。
從更技術的方面來說,沒有映射到隱式對象的標識符是用 PageContext 實例的 findAttribute() 方法求值的,該實例表示對頁面的處理,在該頁面上,當前正在處理用於請求的表達式。標識符的名稱作為參數傳遞給這個方法,然後該方法依次在四個作用域中搜索具有相同名稱的屬性。並將所找到的第一個匹配項作為 findAttribute() 方法的值返回。如果未在這四個作用域中找到這樣的屬性,則返回 null 。
最終,限制了作用域的變數是四個 JSP 作用域的屬性,這些屬性具有可以用作 EL標識符的名稱。只要對限制了作用域的變數賦予由字母數字組成的名稱,就可以通過 JSP 中提供的用於設置屬性的任何機制來創建它們。這包括內置的 操作,以及由 Servlet API 中的幾個類定義的 setAttribute() 方法。此外,四個 JSTL 庫中定義的許多定製標記本身就能夠設置作為限制了作用域的變數使用的屬性值。

隱式對象

表 1 中列出了 11 個 EL 隱式對象的標識符。不要將這些對象與 JSP 隱式對象(一共只有九個)混淆,其中只有一個對象是它們所共有的。
表 1. EL 隱式對象
類別標識符描述
JSP pageContext PageContext 實例對應於當前頁面的處理
作用域pageScope 與頁面作用域屬性的名稱和值相關聯的 Map 類
requestScope 與請求作用域屬性的名稱和值相關聯的 Map 類
sessionScope 與會話作用域屬性的名稱和值相關聯的 Map 類
applicationScope 與應用程序作用域屬性的名稱和值相關聯的 Map 類
請求參數 param 按名稱存儲請求參數的主要值的 Map 類
paramValues 將請求參數的所有值作為 String數組存儲的 Map 類
請求頭 header 按名稱存儲請求頭主要值的 Map 類
headerValues 將請求頭的所有值作為 String數組存儲的 Map 類
Cookie cookie 按名稱存儲請求附帶的 cookie 的 Map 類
初始化參數 initParam 按名稱存儲 Web應用程序上下文初始化參數的 Map 類
儘管 JSP 和 EL 隱式對象中只有一個公共對象( pageContext ),但通過 EL 也可以訪問其它 JSP 隱式對象。原因是 pageContext 擁有訪問所有其它八個 JSP 隱式對象的特性。實際上,這是將它包括在 EL 隱式對象中的主要理由。
其餘所有 EL 隱式對象都是映射,可以用來查找對應於名稱的對象。前四個映射表示先前討論的各種屬性作用域。可以用它們來查找特定作用域中的標識符,而不用依賴於 EL 在預設情況下使用的順序查找過程。
接下來的四個映射用來獲取請求參數和請求頭的值。因為 HTTP 協議允許請求參數和請求頭具有多個值,所以它們各有一對映射。每對中的第一個映射返回請求參數或頭的主要值,通常是恰巧在實際請求中首先指定的那個值。每對中第二個映射允許檢索參數或頭的所有值。這些映射中的鍵是參數或頭的名稱,但這些值是 String 對象的數組,其中的每個元素都是單一參數值或頭值。
cookie 隱式對象提供了對由請求設置的 cookie 名稱的訪問。這個對象將所有與請求相關聯的 cookie 名稱映射到表示那些 cookie 特性的 Cookie 對象。
最後一個 EL 隱式對象 initParam 是一個映射,它儲存與 Web 應用程序相關聯的所有上下文的初始化參數的名稱和值。初始化參數是通過web.xml部署描述符文件指定的,該文件位於應用程序的 WEB-INF 目錄中。

存取器

因為 EL標識符是作為隱式對象或限制了作用域的變數(通過屬性來實現)解析的,因此有必要將它們轉換成 Java 對象。EL 可以自動包裝和解包其相應的 Java 類中的基本類型(例如,可以在後台將 int強制轉換成 Integer 類,反之亦可),但大多數的標識符將成為指向完整的 Java 對象的指針。
結果是,對這些對象的特性或(在對象是數組和集合的情況下)對其元素的訪問通常是令人滿意的。就為了實現這種用途,EL 提供了兩種不同的存取器(點運算符( . )和方括弧運算符( [] )),也支持通過 EL 操作特性和元素。
點運算符通常用於訪問對象的特性。例如,在表達式${user.firstName} 中,使用點運算符來訪問 user標識符所引用對象的名為 firstName 的特性。EL 使用 Java bean 約定訪問對象特性,因此必須定義這個特性的 getter 方法(通常是名為 getFirstName() 的方法),以便表達式正確求值。當被訪問的特性本身是對象時,可以遞歸地應用點運算符。例如,如果我們虛構的 user 對象有一個實現為 Java 對象的 address 特性,那麼也可以用點運算符來訪問這個對象的特性。例如,表達式${user.address.city} 將會返回這個地址對象嵌套的 city 特性。
方括弧運算符用來檢索數組和集合的元素。在數組和有序集合(也即,實現了 java.util.List 介面的集合)的情況下,把要檢索的元素的下標放在方括弧中。例如,表達式${urls[3]} 返回 urls標識符所引用的數組或集合的第四個元素(和 Java 語言以及 JavaScript 中一樣,EL 中的下標是從零開始的)。
對於實現 java.util.Map 介面的集合,方括弧運算符使用關聯的鍵查找存儲在映射中的值。在方括弧中指定鍵,並將相應的值作為表達式的值返回。例如,表達式${commands["dir"]} 返回與 commands標識符所引用的 Map 中的 "dir" 鍵相關聯的值。
對於上述兩種情況,都可允許表達式出現在方括弧中。對嵌套表達式求值的結果將被作為下標或鍵,用來檢索集合或數組的適當元素。和點運算符一樣,方括弧運算符也可以遞歸應用。這使得 EL 能夠從多維數組、嵌套集合或兩者的任意組合中檢索元素。此外,點運算符和方括弧運算符還可以互操作。例如,如果數組的元素本身是對象,則可以使用方括弧運算符來檢索該數組的元素,並結合點運算符來檢索該元素的一個特性(例如 ${urls[3].protocol} )。
假定 EL 充當指定動態屬性值的簡化語言,EL 存取器有一個有趣的功能(與 Java 語言的存取器不同),那就是它們在應用於 null 時不拋出異常。如果應用 EL 存取器的對象(例如, ${foo.bar} 和 ${foo["bar"]} 中的 foo標識符)是 null ,那麼應用存取器的結果也是 null 。事實證明,在大多數情況下,這是一個相當有用的行為,不久您就會了解這一點。
最後,點運算符和方括弧運算符可能實現某種程度的互換。例如,也可以使用 ${user["firstName"]} 來檢索 user 對象的 firstName 特性,正如可以用 ${commands.dir} 獲取與 commands 映射中的 "dir" 鍵相關聯的值一樣。
以下是el表達式對javabean組件、數組,Map集合、List集合中數據調用方法的簡要總結:
數據類型示例用法實際調用方法
JavaBean組件
${colorBean.red}
${colorBean["red"]}
colorBean.getRed()
數組
${colorArray[2]}
${colorArray["2"]}
Array.get(colorArray, 2)
List
colorList[2]
colorList["2"]
colorList.get(2)
Map
colorMap[red]
colorMap["red"]
colorMap.get(pageContext.findAttribute("red"))
colorMap.get("red")

運算符

EL 還可以通過使用標識符和存取器,遍歷包含應用程序數據(通過限制了作用域的變數公開)或關於環境的信息(通過 EL 隱式對象)的對象層次結構。但是,只是訪問這些數據,通常不足以實現許多 JSP應用程序所需的表示邏輯。
最終,EL 還包括了幾個用來操作和比較 EL表達式所訪問數據的運算符。表 2 中匯總了這些運算符。
表 2. EL 運算符
類別運算符
算術運算符 + 、 - 、 * 、 / (或 div )和 % (或 mod )
關係運算符== (或 eq )、 != (或 ne )、 < (或 lt )、 > (或 gt )、 <= (或 le )和 >= (或 ge )
邏輯運算符 && (或 and )、 || (或 or )和 ! (或 not )
驗證運算符 empty
算術運算符支持數值的加法、減法、乘法和除法。還提供了一個求余運算符。註:除法和求余運算符都有替代的、非符號的名稱(為的是與 XPath 保持一致)。清單 5 中顯示了一個演示算術運算符用法的示例表達式。對幾個 EL表達式應用算術運算符的結果是將該算術運算符應用於這些表達式返回的數值所得的結果。
清單 5. 利用算術運算符的 EL 表達式
${item.price * (1 + taxRate[user.address.zipcode])}
關係運算符允許比較數字或文本數據。比較的結果作為布爾值返回。邏輯運算符允許合併布爾值,返回新的布爾值。因此,可以將 EL邏輯運算符應用於嵌套的關係或邏輯運算符的結果,如清單 6 所示。
清單 6. 利用關係和邏輯運算符的 EL 表達式
${(x >= min) && (x <= max)}
最後一種 EL運算符是 empty ,它對於驗證數據特別有用。 empty運算符採用單個表達式作為其變數(也即, ${empty input} ),並返回一個布爾值,該布爾值表示對表達式求值的結果是不是“空”值。求值結果為 null 的表達式被認為是空,即無元素的集合或數組。如果參數是對長度為零的 String 求值所得的結果,則 empty運算符也將返回 true 。
表 3 顯示了 EL 運算符的優先順序。正如清單 5 和 6 所示,可以用圓括弧對表達式分組,高於普通的優先順序規則。
表 3. EL運算符優先順序(自頂到底,從左到右)
[] , .
()
unary - 、 not 、 ! 、 empty
* 、 / 、 div 、 % 、 mod
+ 、binary -
() < 、 > 、 <= 、 >= 、 lt 、 gt 、 le 、 ge
== 、 != 、 eq 、 ne
&& 、 and
|| 、 or

文字

在 EL表達式中,數字、字元串、布爾值和 null 都可以被指定為文字值。字元串可以用單引號或雙引號定界。布爾值被指定為 true 和 false 。
Taglib偽指令
正如我們先前討論的,JSTL 1.0 包括四個定製標記庫。為了演示 JSTL 標記和表達式語言的交互,我們將研究幾個來自 JSTL core 庫的標記。和使用任何 JSP 定製標記庫一樣,必須在您想要使用這個庫標記的任何頁面中包括 taglib 偽指令。清單 7 顯示了用於這個特定庫的偽指令。
清單 7. 用於 JSTL core 庫 EL 版本的 taglib 偽指令
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
實際上,對應於 JSTL core 庫的 taglib 偽指令有兩種,因為在 JSTL 1.0 中,EL 是可選的。所有四個 JSTL 1.0 定製標記庫都有使用 JSP表達式(而不是 EL)指定動態屬性值的備用版本。因為這些備用庫依賴於 JSP 的更傳統的請求時屬性值,所以它們被稱為 RT庫,而那些使用表達式語言的則被稱為 EL 庫。開發人員用不同的 taglib 偽指令來區分每個庫的這兩個版本。清單 8 顯示了使用 core 庫的 RT 版本的偽指令。但是,由於我們討論的重點是 EL,所以首先需要這些偽指令。
清單 8. 用於 JSTL core 庫 RT 版本的 taglib 偽指令
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %>

變數標記

我們首先要考慮的 JSTL 定製標記是 操作。正如已經說明的,限制了作用域的變數在 JSTL 中起關鍵作用, 操作提供基於標記的機制來創建和設置限制了作用域的變數。清單 9 中顯示了該操作的語法,其中 var 屬性指定了限制了作用域的變數的名稱, scope 屬性表明了該變數駐留在哪個作用域中, value 屬性指定了分配給該變數的值。如果指定變數已經存在,則簡單地將所指明的值賦給它。如果不存在,則創建新的限制了作用域的變數,並用該值初始化這個變數。
清單 9. 操作的語法
scope="scope"
value="expression"/>
scope 屬性是可選的,其預設值是 page 。
清單 10 中顯示了 的兩個示例。在第一個示例中,將會話作用域變數設置成 String 值。在第二個示例中,用表達式來設置數值:將頁面作用域內名為 square 的變數賦值為名為 x 的請求參數的值的平方。
清單 10. 操作示例
您還可以將限制了作用域的變數的值指定為 操作的主體內容,而不是使用屬性。使用這種方法,您可以重新編寫清單 10 中的第一個示例,如清單 11 所示。此外,正如我們馬上可以看到的, 標記的主體內容本身也可以使用定製標記。 主體內生成的所有內容都將作為一個 String 值賦給指定變數。
清單 11. 通過主體內容指定 操作的值
CST
JSTL core 庫包含第二個用於管理限制了作用域的變數的標記 ― 。顧名思義, 操作是用來刪除限制了作用域的變數的,它獲取兩個屬性。 var 屬性指定待刪除變數的名稱, scope 屬性是可選的,它表示待刪除變數來自哪個作用域,預設為 page ,如清單 12 所示。
清單 12. 操作示例

輸出

儘管 操作允許將表達式結果賦給限制了作用域的變數,但開發人員通常會希望只顯示錶達式的值,而不存儲它。JSTL 定製標記承擔這一任務,其語法如清單 13 所示。該標記對由其 value 屬性指定的表達式進行求值,然後列印結果。如果指定了可選屬性 default ,那麼,在對 value 屬性的表達式求值所得結果為 null 或空 String 的情況下, 將列印其值。
清單 13. 操作的語法
default="expression"
escapeXml="boolean"/>
escapeXml 屬性也是可選的。它控制當用 標記輸出諸如“<”、“>”和“&”之類的字元(在 HTML 和 XML 中具有特殊意義)時是否應該進行轉義。如果將 escapeXml 設置為 true,則會自動將這些字元轉換成相應的 XML 實體(此處提到的字元分別轉換成 < 、 > 和 & )。
例如,假定有一個名為 user 的會話作用域變數,它是一個類的實例,該類為用戶定義了兩個特性: username 和 company 。每當用戶訪問站點時,這個對象被自動分配給會話,但直到用戶實際登錄后,才會設置這兩個特性。假定是這種方案,請考慮清單 14 中的 JSP 片段。在用戶登錄之後,這個片段將顯示單詞“Hello”,其後是他/她的用戶名和一個驚嘆號。但是,在用戶登錄之前,由這個片段生成的內容則是短語“Hello Guest!”。在這種情況下,因為 username 特性還有待初始化,所以 標記將轉而列印出 default 屬性的值(即字元串“Guest”)。
清單 14. 帶預設內容的 操作示例
Hello !
接下來,考慮清單 15,它使用了 標記的 escapeXml 屬性。如果在這種情況下已經將 company 特性設置成 Java String 值 "Flynn & Sons" ,那麼,實際上該操作生成的內容將是 Flynn & Sons 。如果這個操作是生成 HTML 或 XML 內容的 JSP 頁面的一部分,那麼,這個字元串中間的“&”符號最終可能被解釋為 HTML 或 XML控制字元,從而妨礙了對該內容的顯示或解析。但是,如果將 escapeXml 屬性值設置成 true ,則所生成的內容將是 Flynn & Sons 。瀏覽器或解析器不會因在解釋時遇到這種內容而出問題。假定 HTML 和 XML 是 JSP應用程序中最常見的內容類型,所以 escapeXml 屬性的預設值是 true 就不足為奇了。
清單 15. 禁用轉義的 操作示例
用預設值設置變數
除了簡化動態數據的顯示之外,當通過 設置變數值時, 指定預設值的能力也很有用。正如 清單 11 所示,用來賦給限制了作用域的變數的值可以指定為 標記的主體內容,也可以通過其值屬性來指定。通過將 操作嵌套在 標記的主體內容中,變數賦值就可以利用其預設值能力。
清單 16 中說明了這種方法。外部 標記的行為非常簡單:它根據其主體內容設置會話作用域timezone變數的值。但是,在這種情況下,主體內容是通過 操作生成的。這個嵌套操作的值屬性是表達式${cookie['tzPref'].value} ,它嘗試通過 cookie 隱式對象返回名為 tzPref 的 cookie 值。( cookie 隱式對象將 cookie 名稱映射到相應的 Cookie 實例,這意味著必須通過對象的 value 特性使用點運算符來檢索儲存在 cookie 中的實際數據。)
清單 16. 合併 以提供預設變數值
但是,請考慮以下情況,用戶是第一次嘗試使用這段代碼的 Web 應用程序。結果是,請求中沒有提供名為 tzPref 的 cookie。這意味著使用隱式對象的查找將返回 null ,在這種情況下整個表達式將返回 null 。因為對 標記的 value 屬性求值的結果是 null ,所以 標記會轉而輸出對其 default 屬性求值的結果。在這裡是字元串 CST 。因此,實際的結果是將 timezone 限制了作用域的變數設置成用戶的 tzPref cookie 中存儲的時區,或者,如果沒有,則使用預設時區 CST 。
EL 和 JSP 2.0
表達式語言僅可用於指定 JSTL 定製標記中的動態屬性值。但 JSTL 1.0表達式語言的一個擴展已經被提出,會把它包括到 JSP 2.0 中去,眼下正在進行最後評審。這個擴展將允許開發人員通過自己的定製標記來使用 EL。頁面作者將可以在當前允許使用 JSP表達式的任何地方使用 EL表達式,譬如將動態值插入模板文本中:
Your preferred time zone is $
這個 JSP 2.0 功能(就象 JSTL 本身一樣)將支持頁面作者進一步減少對 JSP 編製腳本元素的依賴,從而改進 JSP應用程序的可維護性。

常用函數

fn:contains(string, substring)
如果參數string中包含參數substring,返回true
fn:containsIgnoreCase(string, substring)
如果參數string中包含參數substring(忽略大小寫),返回true
fn:endsWith(string, suffix)
如果參數 string 以參數suffix結尾,返回true
fn:escapeXml(string)
將有特殊意義的XML (和HTML)轉換為對應的XML實體字元,並返迴轉義后的字元
fn:indexOf(string, substring)
返回參數substring在參數string中第一次出現的位置
fn:join(array, separator)
將一個給定的數組array用給定的間隔符separator串在一起,組成一個新的字元串並返回。
fn:length(item)
返回參數item中包含元素的數量。
參數Item類型是普通對象、數組、Collection、Map、Iterator迭代器、Enumeration枚舉對象、
或者String。
如果是String類型,返回值是String中的字元數。
如果是數組類型,返回值是數組的長度。
如果是Collection容器類的子類,返回值是該容器類的包含元素的個數。
如果是Map類型,返回值是此映射中的鍵-值映射關係數。
如果是Iterator類型,返回值是Iterator中的元素個數。
如果是Enumeration類型,返回值是Enumeration中的元素個數
fn:replace(string, before, after)
返回一個String對象。
用參數after字元串替換參數string中所有出現參數before字元串的地方,並返回替換后的結果
fn:split(string, separator)
返回一個數組,以參數separator 為分割符分割參數string,分割后的每一部分就是數組的一個元素
fn:startsWith(string, prefix)
如果參數string以參數prefix開頭,返回true
fn:substring(string, begin, end)
返回參數string部分字元串, 從參數begin開始到參數end位置,包括end位置的字元
fn:substringAfter(string, substring)
返回參數substring在參數string中後面的那一部分字元串
fn:substringBefore(string, substring)
返回參數substring在參數string中前面的那一部分字元串
fn:toLowerCase(string)
將參數string所有的字元變為小寫,並將其返回
fn:toUpperCase(string)
將參數string所有的字元變為大寫,並將其返回
fn:trim(string)
去除參數string 首尾的空格,並將其返回

結束語

EL(與四個 JSTL 定製標記庫提供的操作結合起來)允許頁面作者不使用腳本元素即可實現表示層邏輯。例如,對比本文開頭 清單 1 中的 JSP代碼和清單 17 中顯示的通過 JSTL 實現的同樣功能。(JSTL core 庫中其餘的標記,包括 及其子標記,將在本系列的下一篇文章中討論。)儘管顯然執行了條件邏輯,但是 JSTL 版本中沒有 Java 語言源代碼,並且標記之間的關係(尤其是關於嵌套需求)對於任何精通 HTML 語法的人都應該是熟悉的。
清單 17. 合併 以提供預設變數值
Welcome, member!
Welcome, guest!
通過提供大多數 Web應用程序常用功能的標準實現,JSTL 有助於加速開發周期。與 EL 結合起來,JSTL 可以不需要對錶示層程序編寫代碼,這極大地簡化了 JSP應用程序的維護。

版本更新歷史


DateItem
2009/04/22Moved to a Maven based build system.
2008/12/21A patch from Robert Goff has moved the trunk of the Standard Taglib up towards JSTL 1.2 level.
10/25/2004Standard Taglib version 1.1.2 - A minor bug fix update - is now available.
07/20/2004Standard Taglib version 1.1.1 released - A minor bug fix update - is now available.
01/30/2004Standard Taglib version 1.1.0 - First official release of our implementation of JSTL 1.1 - is now available.
09/25/2003Standard Taglib version 1.1.0-B1 - early access (Beta 1) of our implementation of JSTL 1.1 - is now available.
參考資料:JSTL官方網站 
  • 目錄