標籤:JSTL

JSTL(JSP Standard Tag Library ,JSP標準標籤庫)是一個不斷完善的開放源代碼的JSP標籤庫,是由apache的jakarta小組來維護的。JSTL只能運行在支持JSP1.2和Servlet2.3規範的容器上,如tomcat 4.x。在JSP 2.0中也是作為標準支持的。

1定義

JSTL 1.0 發佈於 2002 年 6 月,由四個定製標記庫(core、format、xml 和 sql)和一對通用標記庫驗證器(ScriptFreeTLV 和 PermittedTaglibsTLV)組成。core 標記庫提供了定製操作,通過限制了作用域的變數管理數據,以及執行頁面內容的迭代和條件操作。它還提供了用來生成和操作 URL 的標記。顧名思義,format 標記庫定義了用來格式化數據(尤其是數字和日期)的操作。它還支持使用本地化資源束進行 JSP 頁面的國際化。xml 庫包含一些標記,這些標記用來操作通過 XML 表示的數據,而 sql 庫定義了用來查詢關係資料庫的操作。
如果要使用JSTL,則必須將jstl.jar和 standard.jar文件放到classpath中,如果你還需要使用XML processing及Database access (SQL)標籤,還要將相關JAR文件放到classpath中,這些JAR文件全部存在於下載回來的zip文件中。這個zip文件可以從http://jakarta.apacheorg/builds/jakarta-taglibs/releases/standard/jakarta-taglibs-standard-1.0.zip下載。

2使用條件

jstl帶來的優雅編程體驗人所皆知,在java社區蒸蒸日上的今天使用jstl已無需考慮很多問題,我們可以用myeclipse等java集成開發環境輕鬆搭建一個jstl的web項目。即便有了myeclipse這麼得力的工具幫我們快速開發web項目,但是有一些知識我們必須了解的 ---- 那就是jstl與servlet版本,以及jsp版本之間的依賴關係。
以下列出jstl各個版本與jsp及servlet版本之間的依賴關係。
版本號
JSTL 版本
要求(必須滿足此條件)
獲取Taglib途徑
Standard 1.2
JSTL 1.2 (尚未經過JCP認證)
Servlet 2.5, JavaServer Pages 2.1
subversion
Standard 1.1
JSTL 1.1
Servlet 2.4, JavaServer Pages 2.0
下載
Standard 1.0
JSTL 1.0
Servlet 2.3, JavaServer Pages 1.2
下載

3優點

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

4詳細介紹

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")) { %>
<p>Welcome, member!</p>
<% } else { %>
<p>Welcome, guest!</p>
<% } %>
修正此類問題通常需要相當豐富的編程經驗。儘管通常會由十分精通頁面布局和圖形設計的設計人員來開發和維護 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的時候,在頁面顯示數據必須用<c:out>來進行,然而在JSTL1.1中,由於JSP2.0規範已經默認支持EL表達式,因此可以直接在JSP頁面使用表達式,看下面一個例子
<c:out value="${sessionScope.anyValue}" default="no value" escapeXml="false"/>
在EL表達式尚未出現之前,Struts1中一直用<bean:write>輸出變數內容
表達式語言
在 JSP 1.2 中,可以使用靜態字元串或表達式(如果允許的話)指定 JSP 操作的屬性。例如,在清單 2 中,對 <jsp:setProperty> 操作的 name 和 property 屬性指定了靜態值,而用表達式指定了其 value 屬性。這個操作的效果是將請求參數的當前值賦予命名的 bean 特性。以這種形式使用的表達式被稱為 請求時屬性值(request-time attribute value),這是構建到 JSP 規範中的用於動態指定屬性值的唯一機制。
清單 2. 合併請求時屬性值的 JSP 操作
<jsp:setProperty name="user" property="timezonePref"
value='<%= request.getParameter("timezone") %>'/>
因為請求時屬性值是用表達式指定的,所以它們往往有和其它腳本元素一樣的軟體維護問題。因此,JSTL 定製標記支持另一種用於指定動態屬性值的機制。可以用簡化的表達式語言(EL)而不使用完整的 JSP 表達式來指定 JSTL 操作的屬性值。EL 提供了一些標識符、存取器和運算符,用來檢索和操作駐留在 JSP容器中的數據。EL 在某種程度上以 EcmaScript(請參閱 參考資料)和 XML 路徑語言(XML Path Language,XPath)為基礎,因此頁面設計人員和程序員都應該熟悉它的語法。EL 擅長尋找對象及其特性,然後對它們執行簡單操作;它不是編程語言,甚至不是腳本編製語言。但是,與 JSTL 標記一起使用時,它就能使用簡單而又方便的符號來表示複雜的行為。EL表達式的格式是這樣的:用美元符號($)定界,內容包括在花括弧({})中,如清單 3 所示。
清單 3. 說明 EL表達式定界符的 JSTL 操作
<c:out value="${user.firstName}"/>
此外,您可以將多個表達式與靜態文本組合在一起以通過字元串並置來構造動態屬性值,如清單 4 所示。單獨的表達式由標識符、存取器、文字和運算符組成。標識符用來引用存儲在數據中心中的數據對象。EL 有 11 個保留標識符,對應於 11 個 EL 隱式對象。假定所有其它標識符都引用 限制了作用域的變數。存取器用來檢索對象的特性或集合的元素。文字表示固定的值 ― 數字、字元、字元串、布爾型或空值。運算符允許對數據和文字進行組合以及比較。
清單 4. 組合靜態文本和多個 EL表達式以指定動態屬性值
<c:out value="Hello ${user.firstName} ${user.lastName}"/>
限制了作用域的變數
JSP API 通過 <jsp:useBean> 操作允許從 JSP容器內的四個不同作用域中存儲和檢索數據。JSTL 通過提供用於指定和除去這些作用域中的對象的附加操作來擴展這一能力。此外,EL 提供將這些對象作為限制了作用域的變數進行檢索的內置支持。特別地,任何出現在 EL表達式中但不對應於任何 EL 隱式對象的標識符,都被自動假定為引用存儲在四個 JSP作用域的其中某個中的對象,這四個作用域是:
頁面作用域
請求作用域
會話作用域
應用程序作用域
您可能還記得,只有在為特定請求處理頁面期間才能檢索存儲在該頁面作用域中的對象。如果對象是存儲在請求作用域中的,可以在處理所有參與處理某請求的頁面期間檢索這些對象(譬如在對某個請求的處理中遇到了一個或多個 <jsp:include> 或 <jsp:forward> 操作)。如果對象是存儲在會話作用域中的,則在與 Web應用程序的互動式會話期間,可以由用戶訪問的任何頁面檢索它(即,直到與該用戶交互相關聯的 HttpSession 對象無效為止)。可以由任何用戶從任何頁面訪問存儲在應用程序作用域中的對象,直到卸載 Web應用程序本身為止(通常是由於關閉 JSP容器所致)。
通過將字元串映射為期望作用域中的對象來將對象存儲到該作用域。然後,就可以通過提供相同字元串來從該作用域檢索該對象。在作用域的映射中查找字元串,並返回被映射的對象。在 Servlet API 中,將此類對象稱為相應作用域的 屬性。但是,在 EL 的上下文中,也將與屬性相關聯的字元串看作變數的名稱,該變數通過屬性映射的方式獲得特定的值。
在 EL 中,與隱式對象無關聯的標識符被認為是存儲在四個 JSP作用域中的名稱對象。首先對頁面作用域檢查是否存在這樣的標識符,其次對請求作用域、然後對會話作用域、最後對應用程序作用域依次進行這樣的檢查,然後測試該標識符的名稱是否與存儲在該作用域中的某個對象的名稱匹配。第一個這樣的匹配作為 EL標識符的值被返回。通過這種方法,可以將 EL標識符看作引用限制了作用域的變數。
從更技術的方面來說,沒有映射到隱式對象的標識符是用 PageContext 實例的 findAttribute() 方法求值的,該實例表示對頁面的處理,在該頁面上,當前正在處理用於請求的表達式。標識符的名稱作為參數傳遞給這個方法,然後該方法依次在四個作用域中搜索具有相同名稱的屬性。並將所找到的第一個匹配項作為 findAttribute() 方法的值返回。如果未在這四個作用域中找到這樣的屬性,則返回 null 。
最終,限制了作用域的變數是四個 JSP 作用域的屬性,這些屬性具有可以用作 EL標識符的名稱。只要對限制了作用域的變數賦予由字母數字組成的名稱,就可以通過 JSP 中提供的用於設置屬性的任何機制來創建它們。這包括內置的 <jsp:useBean> 操作,以及由 Servlet API 中的幾個類定義的 setAttribute() 方法。此外,四個 JSTL 庫中定義的許多定製標記本身就能夠設置作為限制了作用域的變數使用的屬性值。
存取器
因為 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表達式中,數字、字元串、布爾值和 null 都可以被指定為文字值。字元串可以用單引號或雙引號定界。布爾值被指定為 true 和 false 。
Taglib偽指令
正如我們先前討論的,JSTL 1.0 包括四個定製標記庫。為了演示 JSTL 標記和表達式語言的交互,我們將研究幾個來自 JSTL core 庫的標記。和使用任何 JSP 定製標記庫一樣,必須在您想要使用這個庫標記的任何頁面中包括 taglib 偽指令。清單 7 顯示了用於這個特定庫的偽指令。
清單 7. 用於 JSTL core 庫 EL 版本的 taglib 偽指令
<%@ taglib uri="http://java.suncom/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.suncom/jstl/core_rt" prefix="c_rt" %>
輸出
儘管 <c:set> 操作允許將表達式結果賦給限制了作用域的變數,但開發人員通常會希望只顯示錶達式的值,而不存儲它。JSTL <c:out> 定製標記承擔這一任務,其語法如清單 13 所示。該標記對由其 value 屬性指定的表達式進行求值,然後列印結果。如果指定了可選屬性 default ,那麼,在對 value 屬性的表達式求值所得結果為 null 或空 String 的情況下, <c:out> 將列印其值。
清單 13. <c:out> 操作的語法
<c:out value="expression"
default="expression"
escapeXml="boolean"/>
escapeXml 屬性也是可選的。它控制當用 <c:out> 標記輸出諸如「<」、「>」和「&」之類的字元(在 HTML 和 XML 中具有特殊意義)時是否應該進行轉義。如果將 escapeXml 設置為 true,則會自動將這些字元轉換成相應的 XML 實體(此處提到的字元分別轉換成 < 、 > 和 & )。
例如,假定有一個名為 user 的會話作用域變數,它是一個類的實例,該類為用戶定義了兩個特性: username 和 company 。每當用戶訪問站點時,這個對象被自動分配給會話,但直到用戶實際登錄后,才會設置這兩個特性。假定是這種方案,請考慮清單 14 中的 JSP 片段。在用戶登錄之後,這個片段將顯示單詞「Hello」,其後是他/她的用戶名和一個驚嘆號。但是,在用戶登錄之前,由這個片段生成的內容則是短語「Hello Guest!」。在這種情況下,因為 username 特性還有待初始化,所以 <c:out> 標記將轉而列印出 default 屬性的值(即字元串「Guest」)。
清單 14. 帶預設內容的 <c:out> 操作示例
Hello <c:out value="${user.username}" default=="Guest"/>!
接下來,考慮清單 15,它使用了 <c:out> 標記的 escapeXml 屬性。如果在這種情況下已經將 company 特性設置成 Java String 值 "Flynn & Sons" ,那麼,實際上該操作生成的內容將是 Flynn & Sons 。如果這個操作是生成 HTML 或 XML 內容的 JSP 頁面的一部分,那麼,這個字元串中間的「&」符號最終可能被解釋為 HTML 或 XML控制字元,從而妨礙了對該內容的顯示或解析。但是,如果將 escapeXml 屬性值設置成 true ,則所生成的內容將是 Flynn & Sons 。瀏覽器或解析器不會因在解釋時遇到這種內容而出問題。假定 HTML 和 XML 是 JSP應用程序中最常見的內容類型,所以 escapeXml 屬性的預設值是 true 就不足為奇了。
清單 15. 禁用轉義的 <c:out> 操作示例
<c:out value="${user.company}" escapeXml=="false"/>
用預設值設置變數
除了簡化動態數據的顯示之外,當通過 <c:set> 設置變數值時, <c:out> 指定預設值的能力也很有用。正如 清單 11 所示,用來賦給限制了作用域的變數的值可以指定為 <c:set> 標記的主體內容,也可以通過其值屬性來指定。通過將 <c:out> 操作嵌套在 <c:set> 標記的主體內容中,變數賦值就可以利用其預設值能力。
清單 16 中說明了這種方法。外部 <c:set> 標記的行為非常簡單:它根據其主體內容設置會話作用域timezone變數的值。但是,在這種情況下,主體內容是通過 <c:out> 操作生成的。這個嵌套操作的值屬性是表達式${cookie['tzPref'].value} ,它嘗試通過 cookie 隱式對象返回名為 tzPref 的 cookie 值。( cookie 隱式對象將 cookie 名稱映射到相應的 Cookie 實例,這意味著必須通過對象的 value 特性使用點運算符來檢索儲存在 cookie 中的實際數據。)
清單 16. 合併 <c:set> 和 <c:out> 以提供預設變數值
<c:set var="timezone" scope=="session">
<c:out value="${cookie['tzPref'].value}" default=="CST"/>
</c:set>
但是,請考慮以下情況,用戶是第一次嘗試使用這段代碼的 Web 應用程序。結果是,請求中沒有提供名為 tzPref 的 cookie。這意味著使用隱式對象的查找將返回 null ,在這種情況下整個表達式將返回 null 。因為對 <c:out> 標記的 value 屬性求值的結果是 null ,所以 <c:out> 標記會轉而輸出對其 default 屬性求值的結果。在這裡是字元串 CST 。因此,實際的結果是將 timezone 限制了作用域的變數設置成用戶的 tzPref cookie 中存儲的時區,或者,如果沒有,則使用預設時區 CST 。
EL 和 JSP 2.0
表達式語言僅可用於指定 JSTL 定製標記中的動態屬性值。但 JSTL 1.0表達式語言的一個擴展已經被提出,會把它包括到 JSP 2.0 中去,眼下正在進行最後評審。這個擴展將允許開發人員通過自己的定製標記來使用 EL。頁面作者將可以在當前允許使用 JSP表達式的任何地方使用 EL表達式,譬如將動態值插入模板文本中: <p>Your preferred time zone is $</p> 。
這個 JSP 2.0 功能(就象 JSTL 本身一樣)將支持頁面作者進一步減少對 JSP 編製腳本元素的依賴,從而改進 JSP應用程序的可維護性。
結束語
EL(與四個 JSTL 定製標記庫提供的操作結合起來)允許頁面作者不使用腳本元素即可實現表示層邏輯。例如,對比本文開頭 清單 1 中的 JSP代碼和清單 17 中顯示的通過 JSTL 實現的同樣功能。(JSTL core 庫中其餘的標記,包括 <c:choose> 及其子標記,將在本系列的下一篇文章中討論。)儘管顯然執行了條件邏輯,但是 JSTL 版本中沒有 Java 語言源代碼,並且標記之間的關係(尤其是關於嵌套需求)對於任何精通 HTML 語法的人都應該是熟悉的。
清單 17. 合併 <c:set> 和 <c:out> 以提供預設變數值
<c:choose><c:when test="${user.role == 'member'}">
<p>Welcome, member!</p>
</c:when><c:otherwise>
<p>Welcome, guest!</p>
</c:otherwise></c:choose>
通過提供大多數 Web應用程序常用功能的標準實現,JSTL 有助於加速開發周期。與 EL 結合起來,JSTL 可以不需要對錶示層程序編寫代碼,這極大地簡化了 JSP應用程序的維護。
上一篇[dhtml]    下一篇 [HTA]

相關評論

同義詞:暫無同義詞