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 的支持。
表達式語言
在 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}"/>