<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    鷹翔宇空

    學(xué)習(xí)和生活

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks

    原文引自:http://www-128.ibm.com/developerworks/cn/java/j-jstl0211/index.html

    JSP 標(biāo)準(zhǔn)標(biāo)記庫(kù)(JSP Standard Tag Library,JSTL)是一個(gè)實(shí)現(xiàn) Web 應(yīng)用程序中常見(jiàn)的通用功能的定制標(biāo)記庫(kù)集,這些功能包括迭代和條件判斷、數(shù)據(jù)管理格式化、XML 操作以及數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)。在 developerWorks 上其新系列的第一篇文章中,軟件工程師 Mark Kolb 向您展示了如何使用 JSTL 標(biāo)記來(lái)避免在 JSP 頁(yè)面中使用腳本編制元素。您還將了解如何通過(guò)從表示層刪除源代碼來(lái)簡(jiǎn)化軟件維護(hù)。最后,您將了解 JSTL 經(jīng)過(guò)簡(jiǎn)化的表達(dá)式語(yǔ)言,它允許在不必使用功能齊全的編程語(yǔ)言的情況下對(duì) JSTL 操作指定動(dòng)態(tài)屬性值。

    JavaServer Pages(JSP)是用于 J2EE 平臺(tái)的標(biāo)準(zhǔn)表示層技術(shù)。JSP 技術(shù)提供了用于執(zhí)行計(jì)算(這些計(jì)算用來(lái)動(dòng)態(tài)地生成頁(yè)面內(nèi)容)的腳本編制元素和操作。腳本編制元素允許在 JSP 頁(yè)面中包括程序源代碼,在為響應(yīng)用戶(hù)請(qǐng)求而呈現(xiàn)頁(yè)面時(shí)可以執(zhí)行這些源代碼。操作將計(jì)算操作封裝到很象 HTML 或 XML 標(biāo)記的標(biāo)記中,JSP 頁(yè)面的模板文本通常包含這些標(biāo)記。JSP 規(guī)范只將幾種操作定義成了標(biāo)準(zhǔn),但從 JSP 1.1 開(kāi)始,開(kāi)發(fā)人員已經(jīng)能夠以定制標(biāo)記庫(kù)的方式創(chuàng)建其自己的操作了。

    JSP 標(biāo)準(zhǔn)標(biāo)記庫(kù)(JSTL)是 JSP 1.2 定制標(biāo)記庫(kù)集,這些標(biāo)記庫(kù)實(shí)現(xiàn)大量服務(wù)器端 Java 應(yīng)用程序常用的基本功能。通過(guò)為典型表示層任務(wù)(如數(shù)據(jù)格式化和迭代或條件內(nèi)容)提供標(biāo)準(zhǔn)實(shí)現(xiàn),JSTL 使 JSP 作者可以專(zhuān)注于特定于應(yīng)用程序的開(kāi)發(fā)需求,而不是為這些通用操作“另起爐灶”。

    當(dāng)然,您可以使用 JSP 腳本編制元素(scriptlet、表達(dá)式和聲明)來(lái)實(shí)現(xiàn)此類(lèi)任務(wù)。例如,可以使用三個(gè) scriptlet 實(shí)現(xiàn)條件內(nèi)容,清單 1 中著重顯示了這三個(gè) scriptlet。但是,因?yàn)槟_本編制元素依賴(lài)于在頁(yè)面中嵌入程序源代碼(通常是 Java 代碼),所以對(duì)于使用這些腳本編制元素的 JSP 頁(yè)面,其軟件維護(hù)任務(wù)的復(fù)雜度大大增加了。例如,清單 1 中的 scriptlet 示例嚴(yán)格地依賴(lài)于花括號(hào)的正確匹配。如果不經(jīng)意間引入了一個(gè)語(yǔ)法錯(cuò)誤,則條件內(nèi)容中的嵌套其它 scriptlet 可能會(huì)造成嚴(yán)重破壞,并且在 JSP 容器編譯該頁(yè)面時(shí),要使所產(chǎn)生的錯(cuò)誤信息有意義可能會(huì)很困難。


    清單 1. 通過(guò) scriptlet 實(shí)現(xiàn)條件內(nèi)容

    												
    														<% if (user.getRole() == "member")) { %>
        <p>Welcome, member!</p>
    <% } else { %>
        <p>Welcome, guest!</p>
    <% } %>
    												
    										

    修正此類(lèi)問(wèn)題通常需要相當(dāng)豐富的編程經(jīng)驗(yàn)。盡管通常會(huì)由十分精通頁(yè)面布局和圖形設(shè)計(jì)的設(shè)計(jì)人員來(lái)開(kāi)發(fā)和維護(hù) JSP,但是同一頁(yè)面中的腳本編制元素出現(xiàn)問(wèn)題時(shí),需要程序員的介入。這種狀況將單個(gè)文件中代碼的責(zé)任分擔(dān)給多人,因而使得開(kāi)發(fā)、調(diào)試和增強(qiáng)此類(lèi) JSP 頁(yè)面成為很麻煩的任務(wù)。通過(guò)將常用功能包裝到定制標(biāo)記庫(kù)的標(biāo)準(zhǔn)集合中,JSTL 使 JSP 作者可以減少對(duì)編制腳本元素的需求,甚至可以不需要它們,并避免了相關(guān)的維護(hù)成本。





    回頁(yè)首


    JSTL 1.0

    JSTL 1.0 發(fā)布于 2002 年 6 月,由四個(gè)定制標(biāo)記庫(kù)( coreformat 、 xmlsql )和一對(duì)通用標(biāo)記庫(kù)驗(yàn)證器( ScriptFreeTLVPermittedTaglibsTLV )組成。 core 標(biāo)記庫(kù)提供了定制操作,通過(guò)限制了作用域的變量管理數(shù)據(jù),以及執(zhí)行頁(yè)面內(nèi)容的迭代和條件操作。它還提供了用來(lái)生成和操作 URL 的標(biāo)記。顧名思義, format 標(biāo)記庫(kù)定義了用來(lái)格式化數(shù)據(jù)(尤其是數(shù)字和日期)的操作。它還支持使用本地化資源束進(jìn)行 JSP 頁(yè)面的國(guó)際化。 xml 庫(kù)包含一些標(biāo)記,這些標(biāo)記用來(lái)操作通過(guò) XML 表示的數(shù)據(jù),而 sql 庫(kù)定義了用來(lái)查詢(xún)關(guān)系數(shù)據(jù)庫(kù)的操作。

    兩個(gè) JSTL 標(biāo)記庫(kù)驗(yàn)證器允許開(kāi)發(fā)人員在其 JSP 應(yīng)用程序中強(qiáng)制使用編碼標(biāo)準(zhǔn)??梢耘渲?ScriptFreeTLV 驗(yàn)證器以在 JSP 頁(yè)面中禁用各種類(lèi)型的 JSP 腳本元素 ― scriptlet、表達(dá)式和聲明。類(lèi)似地, PermittedTaglibsTLV 驗(yàn)證器可以用來(lái)限制可能由應(yīng)用程序的 JSP 頁(yè)面訪(fǎng)問(wèn)的定制標(biāo)記庫(kù)集(包括 JSTL 標(biāo)記庫(kù))。

    盡管 JSTL 最終將會(huì)成為 J2EE 平臺(tái)的必需組件,但目前只有少數(shù)應(yīng)用程序服務(wù)器包括它。JSTL 1.0 的參考實(shí)現(xiàn)可作為 Apache 軟件基金會(huì)(Apache Software Foundation)的 Jakarta Taglibs 項(xiàng)目(請(qǐng)參閱 參考資料)的一部分而獲得??梢詫⒃搮⒖紝?shí)現(xiàn)中的定制標(biāo)記庫(kù)合并到任何支持 JSP 1.2 和 Servlet 2.3 規(guī)范的服務(wù)器,以添加對(duì) JSTL 的支持。





    回頁(yè)首


    表達(dá)式語(yǔ)言

    在 JSP 1.2 中,可以使用靜態(tài)字符串或表達(dá)式(如果允許的話(huà))指定 JSP 操作的屬性。例如,在清單 2 中,對(duì) <jsp:setProperty> 操作的 nameproperty 屬性指定了靜態(tài)值,而用表達(dá)式指定了其 value 屬性。這個(gè)操作的效果是將請(qǐng)求參數(shù)的當(dāng)前值賦予命名的 bean 特性。以這種形式使用的表達(dá)式被稱(chēng)為 請(qǐng)求時(shí)屬性值(request-time attribute value),這是構(gòu)建到 JSP 規(guī)范中的用于動(dòng)態(tài)指定屬性值的唯一機(jī)制。


    清單 2. 合并請(qǐng)求時(shí)屬性值的 JSP 操作

    												
    														<jsp:setProperty name="user" property="timezonePref"
                     value='<%= request.getParameter("timezone") %>'/>
    
    												
    										

    因?yàn)檎?qǐng)求時(shí)屬性值是用表達(dá)式指定的,所以它們往往有和其它腳本元素一樣的軟件維護(hù)問(wèn)題。因此,JSTL 定制標(biāo)記支持另一種用于指定動(dòng)態(tài)屬性值的機(jī)制??梢杂煤?jiǎn)化的 表達(dá)式語(yǔ)言(EL)而不使用完整的 JSP 表達(dá)式來(lái)指定 JSTL 操作的屬性值。EL 提供了一些標(biāo)識(shí)符、存取器和運(yùn)算符,用來(lái)檢索和操作駐留在 JSP 容器中的數(shù)據(jù)。EL 在某種程度上以 EcmaScript(請(qǐng)參閱 參考資料)和 XML 路徑語(yǔ)言(XML Path Language,XPath)為基礎(chǔ),因此頁(yè)面設(shè)計(jì)人員和程序員都應(yīng)該熟悉它的語(yǔ)法。EL 擅長(zhǎng)尋找對(duì)象及其特性,然后對(duì)它們執(zhí)行簡(jiǎn)單操作;它不是編程語(yǔ)言,甚至不是腳本編制語(yǔ)言。但是,與 JSTL 標(biāo)記一起使用時(shí),它就能使用簡(jiǎn)單而又方便的符號(hào)來(lái)表示復(fù)雜的行為。EL 表達(dá)式的格式是這樣的:用美元符號(hào)($)定界,內(nèi)容包括在花括號(hào)({})中,如清單 3 所示。


    清單 3. 說(shuō)明 EL 表達(dá)式定界符的 JSTL 操作

    												
    														<c:out value="${user.firstName}"/>
    
    												
    										

    此外,您可以將多個(gè)表達(dá)式與靜態(tài)文本組合在一起以通過(guò)字符串并置來(lái)構(gòu)造動(dòng)態(tài)屬性值,如清單 4 所示。單獨(dú)的表達(dá)式由標(biāo)識(shí)符、存取器、文字和運(yùn)算符組成。標(biāo)識(shí)符用來(lái)引用存儲(chǔ)在數(shù)據(jù)中心中的數(shù)據(jù)對(duì)象。EL 有 11 個(gè)保留標(biāo)識(shí)符,對(duì)應(yīng)于 11 個(gè) EL 隱式對(duì)象。假定所有其它標(biāo)識(shí)符都引用 限制了作用域的變量。存取器用來(lái)檢索對(duì)象的特性或集合的元素。文字表示固定的值 ― 數(shù)字、字符、字符串、布爾型或空值。運(yùn)算符允許對(duì)數(shù)據(jù)和文字進(jìn)行組合以及比較。


    清單 4. 組合靜態(tài)文本和多個(gè) EL 表達(dá)式以指定動(dòng)態(tài)屬性值

    												
    														<c:out value="Hello ${user.firstName} ${user.lastName}"/>
    
    												
    										





    回頁(yè)首


    限制了作用域的變量

    JSP API 通過(guò) <jsp:useBean> 操作允許從 JSP 容器內(nèi)的四個(gè)不同作用域中存儲(chǔ)和檢索數(shù)據(jù)。JSTL 通過(guò)提供用于指定和除去這些作用域中的對(duì)象的附加操作來(lái)擴(kuò)展這一能力。此外,EL 提供將這些對(duì)象作為限制了作用域的變量進(jìn)行檢索的內(nèi)置支持。特別地,任何出現(xiàn)在 EL 表達(dá)式中但不對(duì)應(yīng)于任何 EL 隱式對(duì)象的標(biāo)識(shí)符,都被自動(dòng)假定為引用存儲(chǔ)在四個(gè) JSP 作用域的其中某個(gè)中的對(duì)象,這四個(gè)作用域是:

    • 頁(yè)面作用域
    • 請(qǐng)求作用域
    • 會(huì)話(huà)作用域
    • 應(yīng)用程序作用域

    您可能還記得,只有在為特定請(qǐng)求處理頁(yè)面期間才能檢索存儲(chǔ)在該頁(yè)面作用域中的對(duì)象。如果對(duì)象是存儲(chǔ)在請(qǐng)求作用域中的,可以在處理所有參與處理某請(qǐng)求的頁(yè)面期間檢索這些對(duì)象(譬如在對(duì)某個(gè)請(qǐng)求的處理中遇到了一個(gè)或多個(gè) <jsp:include><jsp:forward> 操作)。如果對(duì)象是存儲(chǔ)在會(huì)話(huà)作用域中的,則在與 Web 應(yīng)用程序的交互式會(huì)話(huà)期間,可以由用戶(hù)訪(fǎng)問(wèn)的任何頁(yè)面檢索它(即,直到與該用戶(hù)交互相關(guān)聯(lián)的 HttpSession 對(duì)象無(wú)效為止)??梢杂扇魏斡脩?hù)從任何頁(yè)面訪(fǎng)問(wèn)存儲(chǔ)在應(yīng)用程序作用域中的對(duì)象,直到卸載 Web 應(yīng)用程序本身為止(通常是由于關(guān)閉 JSP 容器所致)。

    通過(guò)將字符串映射為期望作用域中的對(duì)象來(lái)將對(duì)象存儲(chǔ)到該作用域。然后,就可以通過(guò)提供相同字符串來(lái)從該作用域檢索該對(duì)象。在作用域的映射中查找字符串,并返回被映射的對(duì)象。在 Servlet API 中,將此類(lèi)對(duì)象稱(chēng)為相應(yīng)作用域的 屬性。但是,在 EL 的上下文中,也將與屬性相關(guān)聯(lián)的字符串看作變量的名稱(chēng),該變量通過(guò)屬性映射的方式獲得特定的值。

    在 EL 中,與隱式對(duì)象無(wú)關(guān)聯(lián)的標(biāo)識(shí)符被認(rèn)為是存儲(chǔ)在四個(gè) JSP 作用域中的名稱(chēng)對(duì)象。首先對(duì)頁(yè)面作用域檢查是否存在這樣的標(biāo)識(shí)符,其次對(duì)請(qǐng)求作用域、然后對(duì)會(huì)話(huà)作用域、最后對(duì)應(yīng)用程序作用域依次進(jìn)行這樣的檢查,然后測(cè)試該標(biāo)識(shí)符的名稱(chēng)是否與存儲(chǔ)在該作用域中的某個(gè)對(duì)象的名稱(chēng)匹配。第一個(gè)這樣的匹配作為 EL 標(biāo)識(shí)符的值被返回。通過(guò)這種方法,可以將 EL 標(biāo)識(shí)符看作引用限制了作用域的變量。

    從更技術(shù)的方面來(lái)說(shuō),沒(méi)有映射到隱式對(duì)象的標(biāo)識(shí)符是用 PageContext 實(shí)例的 findAttribute() 方法求值的,該實(shí)例表示對(duì)頁(yè)面的處理,在該頁(yè)面上,當(dāng)前正在處理用于請(qǐng)求的表達(dá)式。標(biāo)識(shí)符的名稱(chēng)作為參數(shù)傳遞給這個(gè)方法,然后該方法依次在四個(gè)作用域中搜索具有相同名稱(chēng)的屬性。并將所找到的第一個(gè)匹配項(xiàng)作為 findAttribute() 方法的值返回。如果未在這四個(gè)作用域中找到這樣的屬性,則返回 null 。

    最終,限制了作用域的變量是四個(gè) JSP 作用域的屬性,這些屬性具有可以用作 EL 標(biāo)識(shí)符的名稱(chēng)。只要對(duì)限制了作用域的變量賦予由字母數(shù)字組成的名稱(chēng),就可以通過(guò) JSP 中提供的用于設(shè)置屬性的任何機(jī)制來(lái)創(chuàng)建它們。這包括內(nèi)置的 <jsp:useBean> 操作,以及由 Servlet API 中的幾個(gè)類(lèi)定義的 setAttribute() 方法。此外,四個(gè) JSTL 庫(kù)中定義的許多定制標(biāo)記本身就能夠設(shè)置作為限制了作用域的變量使用的屬性值。





    回頁(yè)首


    隱式對(duì)象

    表 1 中列出了 11 個(gè) EL 隱式對(duì)象的標(biāo)識(shí)符。不要將這些對(duì)象與 JSP 隱式對(duì)象(一共只有九個(gè))混淆,其中只有一個(gè)對(duì)象是它們所共有的。

    表 1. EL 隱式對(duì)象

    類(lèi)別 標(biāo)識(shí)符 描述
    JSP pageContext PageContext 實(shí)例對(duì)應(yīng)于當(dāng)前頁(yè)面的處理
    作用域 pageScope 與頁(yè)面作用域?qū)傩缘拿Q(chēng)和值相關(guān)聯(lián)的 Map 類(lèi)
    requestScope 與請(qǐng)求作用域?qū)傩缘拿Q(chēng)和值相關(guān)聯(lián)的 Map 類(lèi)
    sessionScope 與會(huì)話(huà)作用域?qū)傩缘拿Q(chēng)和值相關(guān)聯(lián)的 Map 類(lèi)
    applicationScope 與應(yīng)用程序作用域?qū)傩缘拿Q(chēng)和值相關(guān)聯(lián)的 Map 類(lèi)
    請(qǐng)求參數(shù) param 按名稱(chēng)存儲(chǔ)請(qǐng)求參數(shù)的主要值的 Map 類(lèi)
    paramValues 將請(qǐng)求參數(shù)的所有值作為 String 數(shù)組存儲(chǔ)的 Map 類(lèi)
    請(qǐng)求頭 header 按名稱(chēng)存儲(chǔ)請(qǐng)求頭主要值的 Map 類(lèi)
    headerValues 將請(qǐng)求頭的所有值作為 String 數(shù)組存儲(chǔ)的 Map 類(lèi)
    Cookie cookie 按名稱(chēng)存儲(chǔ)請(qǐng)求附帶的 cookie 的 Map 類(lèi)
    初始化參數(shù) initParam 按名稱(chēng)存儲(chǔ) Web 應(yīng)用程序上下文初始化參數(shù)的 Map 類(lèi)

    盡管 JSP 和 EL 隱式對(duì)象中只有一個(gè)公共對(duì)象( pageContext ),但通過(guò) EL 也可以訪(fǎng)問(wèn)其它 JSP 隱式對(duì)象。原因是 pageContext 擁有訪(fǎng)問(wèn)所有其它八個(gè) JSP 隱式對(duì)象的特性。實(shí)際上,這是將它包括在 EL 隱式對(duì)象中的主要理由。

    其余所有 EL 隱式對(duì)象都是映射,可以用來(lái)查找對(duì)應(yīng)于名稱(chēng)的對(duì)象。前四個(gè)映射表示先前討論的各種屬性作用域。可以用它們來(lái)查找特定作用域中的標(biāo)識(shí)符,而不用依賴(lài)于 EL 在缺省情況下使用的順序查找過(guò)程。

    接下來(lái)的四個(gè)映射用來(lái)獲取請(qǐng)求參數(shù)和請(qǐng)求頭的值。因?yàn)?HTTP 協(xié)議允許請(qǐng)求參數(shù)和請(qǐng)求頭具有多個(gè)值,所以它們各有一對(duì)映射。每對(duì)中的第一個(gè)映射返回請(qǐng)求參數(shù)或頭的主要值,通常是恰巧在實(shí)際請(qǐng)求中首先指定的那個(gè)值。每對(duì)中第二個(gè)映射允許檢索參數(shù)或頭的所有值。這些映射中的鍵是參數(shù)或頭的名稱(chēng),但這些值是 String 對(duì)象的數(shù)組,其中的每個(gè)元素都是單一參數(shù)值或頭值。

    cookie 隱式對(duì)象提供了對(duì)由請(qǐng)求設(shè)置的 cookie 名稱(chēng)的訪(fǎng)問(wèn)。這個(gè)對(duì)象將所有與請(qǐng)求相關(guān)聯(lián)的 cookie 名稱(chēng)映射到表示那些 cookie 特性的 Cookie 對(duì)象。

    最后一個(gè) EL 隱式對(duì)象 initParam 是一個(gè)映射,它儲(chǔ)存與 Web 應(yīng)用程序相關(guān)聯(lián)的所有上下文的初始化參數(shù)的名稱(chēng)和值。初始化參數(shù)是通過(guò) web.xml 部署描述符文件指定的,該文件位于應(yīng)用程序的 WEB-INF 目錄中。





    回頁(yè)首


    存取器

    因?yàn)?EL 標(biāo)識(shí)符是作為隱式對(duì)象或限制了作用域的變量(通過(guò)屬性來(lái)實(shí)現(xiàn))解析的,因此有必要將它們轉(zhuǎn)換成 Java 對(duì)象。EL 可以自動(dòng)包裝和解包其相應(yīng)的 Java 類(lèi)中的基本類(lèi)型(例如,可以在后臺(tái)將 int 強(qiáng)制轉(zhuǎn)換成 Integer 類(lèi),反之亦可),但大多數(shù)的標(biāo)識(shí)符將成為指向完整的 Java 對(duì)象的指針。

    結(jié)果是,對(duì)這些對(duì)象的特性或(在對(duì)象是數(shù)組和集合的情況下)對(duì)其元素的訪(fǎng)問(wèn)通常是令人滿(mǎn)意的。就為了實(shí)現(xiàn)這種用途,EL 提供了兩種不同的存取器(點(diǎn)運(yùn)算符( . )和方括號(hào)運(yùn)算符( [] )),也支持通過(guò) EL 操作特性和元素。

    點(diǎn)運(yùn)算符通常用于訪(fǎng)問(wèn)對(duì)象的特性。例如,在表達(dá)式 ${user.firstName} 中,使用點(diǎn)運(yùn)算符來(lái)訪(fǎng)問(wèn) user 標(biāo)識(shí)符所引用對(duì)象的名為 firstName 的特性。EL 使用 Java bean 約定訪(fǎng)問(wèn)對(duì)象特性,因此必須定義這個(gè)特性的 getter 方法(通常是名為 getFirstName() 的方法),以便表達(dá)式正確求值。當(dāng)被訪(fǎng)問(wèn)的特性本身是對(duì)象時(shí),可以遞歸地應(yīng)用點(diǎn)運(yùn)算符。例如,如果我們虛構(gòu)的 user 對(duì)象有一個(gè)實(shí)現(xiàn)為 Java 對(duì)象的 address 特性,那么也可以用點(diǎn)運(yùn)算符來(lái)訪(fǎng)問(wèn)這個(gè)對(duì)象的特性。例如,表達(dá)式 ${user.address.city} 將會(huì)返回這個(gè)地址對(duì)象嵌套的 city 特性。

    方括號(hào)運(yùn)算符用來(lái)檢索數(shù)組和集合的元素。在數(shù)組和有序集合(也即,實(shí)現(xiàn)了 java.util.List 接口的集合)的情況下,把要檢索的元素的下標(biāo)放在方括號(hào)中。例如,表達(dá)式 ${urls[3]} 返回 urls 標(biāo)識(shí)符所引用的數(shù)組或集合的第四個(gè)元素(和 Java 語(yǔ)言以及 JavaScript 中一樣,EL 中的下標(biāo)是從零開(kāi)始的)。

    對(duì)于實(shí)現(xiàn) java.util.Map 接口的集合,方括號(hào)運(yùn)算符使用關(guān)聯(lián)的鍵查找存儲(chǔ)在映射中的值。在方括號(hào)中指定鍵,并將相應(yīng)的值作為表達(dá)式的值返回。例如,表達(dá)式 ${commands["dir"]} 返回與 commands 標(biāo)識(shí)符所引用的 Map 中的 "dir" 鍵相關(guān)聯(lián)的值。

    對(duì)于上述兩種情況,都可允許表達(dá)式出現(xiàn)在方括號(hào)中。對(duì)嵌套表達(dá)式求值的結(jié)果將被作為下標(biāo)或鍵,用來(lái)檢索集合或數(shù)組的適當(dāng)元素。和點(diǎn)運(yùn)算符一樣,方括號(hào)運(yùn)算符也可以遞歸應(yīng)用。這使得 EL 能夠從多維數(shù)組、嵌套集合或兩者的任意組合中檢索元素。此外,點(diǎn)運(yùn)算符和方括號(hào)運(yùn)算符還可以互操作。例如,如果數(shù)組的元素本身是對(duì)象,則可以使用方括號(hào)運(yùn)算符來(lái)檢索該數(shù)組的元素,并結(jié)合點(diǎn)運(yùn)算符來(lái)檢索該元素的一個(gè)特性(例如 ${urls[3].protocol} )。

    假定 EL 充當(dāng)指定動(dòng)態(tài)屬性值的簡(jiǎn)化語(yǔ)言,EL 存取器有一個(gè)有趣的功能(與 Java 語(yǔ)言的存取器不同),那就是它們?cè)趹?yīng)用于 null 時(shí)不拋出異常。如果應(yīng)用 EL 存取器的對(duì)象(例如, ${foo.bar}${foo["bar"]} 中的 foo 標(biāo)識(shí)符)是 null ,那么應(yīng)用存取器的結(jié)果也是 null 。事實(shí)證明,在大多數(shù)情況下,這是一個(gè)相當(dāng)有用的行為,不久您就會(huì)了解這一點(diǎn)。

    最后,點(diǎn)運(yùn)算符和方括號(hào)運(yùn)算符可能實(shí)現(xiàn)某種程度的互換。例如,也可以使用 ${user["firstName"]} 來(lái)檢索 user 對(duì)象的 firstName 特性,正如可以用 ${commands.dir} 獲取與 commands 映射中的 "dir" 鍵相關(guān)聯(lián)的值一樣。





    回頁(yè)首


    運(yùn)算符

    EL 還可以通過(guò)使用標(biāo)識(shí)符和存取器,遍歷包含應(yīng)用程序數(shù)據(jù)(通過(guò)限制了作用域的變量公開(kāi))或關(guān)于環(huán)境的信息(通過(guò) EL 隱式對(duì)象)的對(duì)象層次結(jié)構(gòu)。但是,只是訪(fǎng)問(wèn)這些數(shù)據(jù),通常不足以實(shí)現(xiàn)許多 JSP 應(yīng)用程序所需的表示邏輯。

    最終,EL 還包括了幾個(gè)用來(lái)操作和比較 EL 表達(dá)式所訪(fǎng)問(wèn)數(shù)據(jù)的運(yùn)算符。表 2 中匯總了這些運(yùn)算符。

    表 2. EL 運(yùn)算符

    類(lèi)別 運(yùn)算符
    算術(shù)運(yùn)算符 + - 、 * 、 / (或 div )和 % (或 mod
    關(guān)系運(yùn)算符 == (或 eq )、 != (或 ne )、 < (或 lt )、 > (或 gt )、 <= (或 le )和 >= (或 ge
    邏輯運(yùn)算符 && (或 and )、 || (或 or )和 ! (或 not
    驗(yàn)證運(yùn)算符 empty

    算術(shù)運(yùn)算符支持?jǐn)?shù)值的加法、減法、乘法和除法。還提供了一個(gè)求余運(yùn)算符。注:除法和求余運(yùn)算符都有替代的、非符號(hào)的名稱(chēng)(為的是與 XPath 保持一致)。清單 5 中顯示了一個(gè)演示算術(shù)運(yùn)算符用法的示例表達(dá)式。對(duì)幾個(gè) EL 表達(dá)式應(yīng)用算術(shù)運(yùn)算符的結(jié)果是將該算術(shù)運(yùn)算符應(yīng)用于這些表達(dá)式返回的數(shù)值所得的結(jié)果。


    清單 5. 利用算術(shù)運(yùn)算符的 EL 表達(dá)式

    												
    														${item.price * (1 + taxRate[user.address.zipcode])}
    
    												
    										

    關(guān)系運(yùn)算符允許比較數(shù)字或文本數(shù)據(jù)。比較的結(jié)果作為布爾值返回。邏輯運(yùn)算符允許合并布爾值,返回新的布爾值。因此,可以將 EL 邏輯運(yùn)算符應(yīng)用于嵌套的關(guān)系或邏輯運(yùn)算符的結(jié)果,如清單 6 所示。


    清單 6. 利用關(guān)系和邏輯運(yùn)算符的 EL 表達(dá)式

    												
    														${(x >= min) && (x <= max)}
    
    												
    										

    最后一種 EL 運(yùn)算符是 empty ,它對(duì)于驗(yàn)證數(shù)據(jù)特別有用。 empty 運(yùn)算符采用單個(gè)表達(dá)式作為其變量(也即, ${empty input} ),并返回一個(gè)布爾值,該布爾值表示對(duì)表達(dá)式求值的結(jié)果是不是“空”值。求值結(jié)果為 null 的表達(dá)式被認(rèn)為是空,即無(wú)元素的集合或數(shù)組。如果參數(shù)是對(duì)長(zhǎng)度為零的 String 求值所得的結(jié)果,則 empty 運(yùn)算符也將返回 true

    表 3 顯示了 EL 運(yùn)算符的優(yōu)先級(jí)。正如清單 5 和 6 所示,可以用圓括號(hào)對(duì)表達(dá)式分組,高于普通的優(yōu)先級(jí)規(guī)則。

    表 3. EL 運(yùn)算符優(yōu)先級(jí)(自頂?shù)降?,從左到右?/strong>

    [] , .
    ()
    unary - 、 not 、 ! 、 empty
    * 、 /div% 、 mod
    + 、binary -
    () <</code> 、 > 、 <= 、 >=ltgt 、 le 、 ge
    == != 、 eqne
    && 、 and
    || or





    回頁(yè)首


    文字

    在 EL 表達(dá)式中,數(shù)字、字符串、布爾值和 null 都可以被指定為文字值。字符串可以用單引號(hào)或雙引號(hào)定界。布爾值被指定為 truefalse 。





    回頁(yè)首


    Taglib 偽指令

    正如我們先前討論的,JSTL 1.0 包括四個(gè)定制標(biāo)記庫(kù)。為了演示 JSTL 標(biāo)記和表達(dá)式語(yǔ)言的交互,我們將研究幾個(gè)來(lái)自 JSTL core 庫(kù)的標(biāo)記。和使用任何 JSP 定制標(biāo)記庫(kù)一樣,必須在您想要使用這個(gè)庫(kù)標(biāo)記的任何頁(yè)面中包括 taglib 偽指令。清單 7 顯示了用于這個(gè)特定庫(kù)的偽指令。


    清單 7. 用于 JSTL core 庫(kù) EL 版本的 taglib 偽指令

    												
    														<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
    
    												
    										

    實(shí)際上,對(duì)應(yīng)于 JSTL core 庫(kù)的 taglib 偽指令有兩種,因?yàn)樵?JSTL 1.0 中,EL 是可選的。所有四個(gè) JSTL 1.0 定制標(biāo)記庫(kù)都有使用 JSP 表達(dá)式(而不是 EL)指定動(dòng)態(tài)屬性值的備用版本。因?yàn)檫@些備用庫(kù)依賴(lài)于 JSP 的更傳統(tǒng)的請(qǐng)求時(shí)屬性值,所以它們被稱(chēng)為 RT庫(kù),而那些使用表達(dá)式語(yǔ)言的則被稱(chēng)為 EL 庫(kù)。開(kāi)發(fā)人員用不同的 taglib 偽指令來(lái)區(qū)分每個(gè)庫(kù)的這兩個(gè)版本。清單 8 顯示了使用 core 庫(kù)的 RT 版本的偽指令。但是,由于現(xiàn)在我們討論的重點(diǎn)是 EL,所以首先需要這些偽指令。


    清單 8. 用于 JSTL core 庫(kù) RT 版本的 taglib 偽指令

    												
    														<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %>
    
    												
    										





    回頁(yè)首


    變量標(biāo)記

    我們首先要考慮的 JSTL 定制標(biāo)記是 <c:set> 操作。正如已經(jīng)說(shuō)明的,限制了作用域的變量在 JSTL 中起關(guān)鍵作用, <c:set> 操作提供基于標(biāo)記的機(jī)制來(lái)創(chuàng)建和設(shè)置限制了作用域的變量。清單 9 中顯示了該操作的語(yǔ)法,其中 var 屬性指定了限制了作用域的變量的名稱(chēng), scope 屬性表明了該變量駐留在哪個(gè)作用域中, value 屬性指定了分配給該變量的值。如果指定變量已經(jīng)存在,則簡(jiǎn)單地將所指明的值賦給它。如果不存在,則創(chuàng)建新的限制了作用域的變量,并用該值初始化這個(gè)變量。


    清單 9. <c:set> 操作的語(yǔ)法

    												
    														<c:set var="
            name" scope="
            scope" value="
            expression"/>
    
          
    												
    										

    scope 屬性是可選的,其缺省值是 page 。

    清單 10 中顯示了 <c:set> 的兩個(gè)示例。在第一個(gè)示例中,將會(huì)話(huà)作用域變量設(shè)置成 String 值。在第二個(gè)示例中,用表達(dá)式來(lái)設(shè)置數(shù)值:將頁(yè)面作用域內(nèi)名為 square 的變量賦值為名為 x 的請(qǐng)求參數(shù)的值的平方。


    清單 10. <c:set> 操作示例

    												
    														<c:set var="timezone" scope="session" value="CST"/>
    <c:set var="square" value="${param['x'] * param['x']}"/>
    
    												
    										

    您還可以將限制了作用域的變量的值指定為 <c:set> 操作的主體內(nèi)容,而不是使用屬性。使用這種方法,您可以重新編寫(xiě)清單 10 中的第一個(gè)示例,如清單 11 所示。此外,正如我們馬上可以看到的, <c:set> 標(biāo)記的主體內(nèi)容本身也可以使用定制標(biāo)記。 <c:set> 主體內(nèi)生成的所有內(nèi)容都將作為一個(gè) String 值賦給指定變量。


    清單 11. 通過(guò)主體內(nèi)容指定 <c:set> 操作的值

    												
    														<c:set var="timezone" scope="session">CST</c:set>
    
    												
    										

    JSTL core 庫(kù)包含第二個(gè)用于管理限制了作用域的變量的標(biāo)記 ― <c:remove> 。顧名思義, <c:remove> 操作是用來(lái)刪除限制了作用域的變量的,它獲取兩個(gè)屬性。 var 屬性指定待刪除變量的名稱(chēng), scope 屬性是可選的,它表示待刪除變量來(lái)自哪個(gè)作用域,缺省為 page ,如清單 12 所示。

    清單 12. <c:remove> 操作示例

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





    回頁(yè)首


    輸出

    盡管 <c:set> 操作允許將表達(dá)式結(jié)果賦給限制了作用域的變量,但開(kāi)發(fā)人員通常會(huì)希望只顯示表達(dá)式的值,而不存儲(chǔ)它。JSTL <c:out> 定制標(biāo)記承擔(dān)這一任務(wù),其語(yǔ)法如清單 13 所示。該標(biāo)記對(duì)由其 value 屬性指定的表達(dá)式進(jìn)行求值,然后打印結(jié)果。如果指定了可選屬性 default ,那么,在對(duì) value 屬性的表達(dá)式求值所得結(jié)果為 null 或空 String 的情況下, <c:out> 將打印其值。


    清單 13. <c:out> 操作的語(yǔ)法

    												
    														<c:out value="
            expression" default="
            expression" escapeXml="
            boolean"/>
    
          
    												
    										

    escapeXml 屬性也是可選的。它控制當(dāng)用 <c:out> 標(biāo)記輸出諸如“<”、“>”和“&”之類(lèi)的字符(在 HTML 和 XML 中具有特殊意義)時(shí)是否應(yīng)該進(jìn)行轉(zhuǎn)義。如果將 escapeXml 設(shè)置為 true,則會(huì)自動(dòng)將這些字符轉(zhuǎn)換成相應(yīng)的 XML 實(shí)體(此處提到的字符分別轉(zhuǎn)換成 < 、 >& )。

    例如,假定有一個(gè)名為 user 的會(huì)話(huà)作用域變量,它是一個(gè)類(lèi)的實(shí)例,該類(lèi)為用戶(hù)定義了兩個(gè)特性: usernamecompany 。每當(dāng)用戶(hù)訪(fǎng)問(wèn)站點(diǎn)時(shí),這個(gè)對(duì)象被自動(dòng)分配給會(huì)話(huà),但直到用戶(hù)實(shí)際登錄后,才會(huì)設(shè)置這兩個(gè)特性。假定是這種方案,請(qǐng)考慮清單 14 中的 JSP 片段。在用戶(hù)登錄之后,這個(gè)片段將顯示單詞“Hello”,其后是他/她的用戶(hù)名和一個(gè)驚嘆號(hào)。但是,在用戶(hù)登錄之前,由這個(gè)片段生成的內(nèi)容則是短語(yǔ)“Hello Guest!”。在這種情況下,因?yàn)?username 特性還有待初始化,所以 <c:out> 標(biāo)記將轉(zhuǎn)而打印出 default 屬性的值(即字符串“Guest”)。


    清單 14. 帶缺省內(nèi)容的 <c:out> 操作示例

    												
    														Hello <c:out value="${user.username}" default=="Guest"/>!
    
    												
    										

    接下來(lái),考慮清單 15,它使用了 <c:out> 標(biāo)記的 escapeXml 屬性。如果在這種情況下已經(jīng)將 company 特性設(shè)置成 Java String"Flynn & Sons" ,那么,實(shí)際上該操作生成的內(nèi)容將是 Flynn & Sons 。如果這個(gè)操作是生成 HTML 或 XML 內(nèi)容的 JSP 頁(yè)面的一部分,那么,這個(gè)字符串中間的“&”符號(hào)最終可能被解釋為 HTML 或 XML 控制字符,從而妨礙了對(duì)該內(nèi)容的顯示或解析。但是,如果將 escapeXml 屬性值設(shè)置成 true ,則所生成的內(nèi)容將是 Flynn & Sons 。瀏覽器或解析器不會(huì)因在解釋時(shí)遇到這種內(nèi)容而出問(wèn)題。假定 HTML 和 XML 是 JSP 應(yīng)用程序中最常見(jiàn)的內(nèi)容類(lèi)型,所以 escapeXml 屬性的缺省值是 true 就不足為奇了。


    清單 15. 禁用轉(zhuǎn)義的 <c:out> 操作示例

    												
    														<c:out value="${user.company}" escapeXml=="false"/>
    
    												
    										





    回頁(yè)首


    用缺省值設(shè)置變量

    除了簡(jiǎn)化動(dòng)態(tài)數(shù)據(jù)的顯示之外,當(dāng)通過(guò) <c:set> 設(shè)置變量值時(shí), <c:out> 指定缺省值的能力也很有用。正如 清單 11 所示,用來(lái)賦給限制了作用域的變量的值可以指定為 <c:set> 標(biāo)記的主體內(nèi)容,也可以通過(guò)其值屬性來(lái)指定。通過(guò)將 <c:out> 操作嵌套在 <c:set> 標(biāo)記的主體內(nèi)容中,變量賦值就可以利用其缺省值能力。

    清單 16 中說(shuō)明了這種方法。外部 <c:set> 標(biāo)記的行為非常簡(jiǎn)單:它根據(jù)其主體內(nèi)容設(shè)置會(huì)話(huà)作用域 timezone 變量的值。但是,在這種情況下,主體內(nèi)容是通過(guò) <c:out> 操作生成的。這個(gè)嵌套操作的值屬性是表達(dá)式 ${cookie['tzPref'].value} ,它嘗試通過(guò) cookie 隱式對(duì)象返回名為 tzPref 的 cookie 值。( cookie 隱式對(duì)象將 cookie 名稱(chēng)映射到相應(yīng)的 Cookie 實(shí)例,這意味著必須通過(guò)對(duì)象的 value 特性使用點(diǎn)運(yùn)算符來(lái)檢索儲(chǔ)存在 cookie 中的實(shí)際數(shù)據(jù)。)


    清單 16. 合并 <c:set> 和 <c:out> 以提供缺省變量值

    												
    														<c:set var="timezone" scope=="session">
       <c:out value="${cookie['tzPref'].value}" default=="CST"/>
    </c:set>
    
    												
    										

    但是,請(qǐng)考慮以下情況,用戶(hù)是第一次嘗試使用這段代碼的 Web 應(yīng)用程序。結(jié)果是,請(qǐng)求中沒(méi)有提供名為 tzPref 的 cookie。這意味著使用隱式對(duì)象的查找將返回 null ,在這種情況下整個(gè)表達(dá)式將返回 null 。因?yàn)閷?duì) <c:out> 標(biāo)記的 value 屬性求值的結(jié)果是 null ,所以 <c:out> 標(biāo)記會(huì)轉(zhuǎn)而輸出對(duì)其 default 屬性求值的結(jié)果。在這里是字符串 CST 。因此,實(shí)際的結(jié)果是將 timezone 限制了作用域的變量設(shè)置成用戶(hù)的 tzPref cookie 中存儲(chǔ)的時(shí)區(qū),或者,如果沒(méi)有,則使用缺省時(shí)區(qū) CST 。

    EL 和 JSP 2.0

    目前,表達(dá)式語(yǔ)言?xún)H可用于指定 JSTL 定制標(biāo)記中的動(dòng)態(tài)屬性值。但 JSTL 1.0 表達(dá)式語(yǔ)言的一個(gè)擴(kuò)展已經(jīng)被提出,會(huì)把它包括到 JSP 2.0 中去,眼下正在進(jìn)行最后評(píng)審。這個(gè)擴(kuò)展將允許開(kāi)發(fā)人員通過(guò)自己的定制標(biāo)記來(lái)使用 EL。頁(yè)面作者將可以在目前允許使用 JSP 表達(dá)式的任何地方使用 EL 表達(dá)式,譬如將動(dòng)態(tài)值插入模板文本中: <p>Your preferred time zone is ${timezone}</p> 。

    這個(gè) JSP 2.0 功能(就象 JSTL 本身一樣)將支持頁(yè)面作者進(jìn)一步減少對(duì) JSP 編制腳本元素的依賴(lài),從而改進(jìn) JSP 應(yīng)用程序的可維護(hù)性。





    回頁(yè)首


    結(jié)束語(yǔ)

    EL(與四個(gè) JSTL 定制標(biāo)記庫(kù)提供的操作結(jié)合起來(lái))允許頁(yè)面作者不使用腳本元素即可實(shí)現(xiàn)表示層邏輯。例如,對(duì)比本文開(kāi)頭 清單 1 中的 JSP 代碼和清單 17 中顯示的通過(guò) JSTL 實(shí)現(xiàn)的同樣功能。(JSTL core 庫(kù)中其余的標(biāo)記,包括 <c:choose> 及其子標(biāo)記,將在本系列的下一篇文章中討論。)盡管顯然執(zhí)行了條件邏輯,但是 JSTL 版本中沒(méi)有 Java 語(yǔ)言源代碼,并且標(biāo)記之間的關(guān)系(尤其是關(guān)于嵌套需求)對(duì)于任何精通 HTML 語(yǔ)法的人都應(yīng)該是熟悉的。


    清單 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>
    												
    										

    通過(guò)提供大多數(shù) Web 應(yīng)用程序常用功能的標(biāo)準(zhǔn)實(shí)現(xiàn),JSTL 有助于加速開(kāi)發(fā)周期。與 EL 結(jié)合起來(lái),JSTL 可以不需要對(duì)表示層程序編寫(xiě)代碼,這極大地簡(jiǎn)化了 JSP 應(yīng)用程序的維護(hù)。





    回頁(yè)首


    參考資料





    回頁(yè)首


    關(guān)于作者

    Mark Kolb 是一名在德克薩斯州奧斯汀工作的軟件工程師。他經(jīng)常就服務(wù)器端 Java 主題在業(yè)界發(fā)表演講,并且與人合著了 Web Development with JavaServer Pages,第二版一書(shū)??赏ㄟ^(guò) mak@taglib.com與 Mark 聯(lián)系。

    posted on 2006-05-16 11:34 TrampEagle 閱讀(331) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): web
    主站蜘蛛池模板: 最近2019年免费中文字幕高清| 日本亚洲免费无线码| 手机在线看永久av片免费| 亚洲 小说区 图片区 都市| 亚洲AV永久纯肉无码精品动漫 | 久久青草免费91线频观看不卡 | 亚洲毛片免费观看| 免费欧洲毛片A级视频无风险| 亚洲男人天堂2017| 国产亚洲精品第一综合| 无码国产精品一区二区免费vr| 精品免费国产一区二区| 亚洲人成网站影音先锋播放| 国产偷国产偷亚洲清高APP| 99精品视频在线免费观看| 免费在线观看日韩| 亚洲国产成人精品久久| 一级一黄在线观看视频免费| 日韩精品福利片午夜免费观着 | 亚洲综合另类小说色区色噜噜| 亚洲人成影院77777| 国产在线观看xxxx免费| 成人黄18免费视频| 亚洲一卡2卡三卡4卡有限公司 | 日本一区二区在线免费观看| 99久久免费国产精品特黄| 亚洲一区二区三区影院| 国产精品亚洲精品久久精品 | 亚洲色婷婷综合开心网| 国产成人精品日本亚洲18图| 成人精品一区二区三区不卡免费看| 国产精品免费看久久久无码| 亚洲成人网在线播放| 免费看成人AA片无码视频吃奶| 国产成人免费ā片在线观看| 亚洲人成网网址在线看| 国产精品免费观看调教网| 亚洲一级特黄大片在线观看| 亚洲精品成a人在线观看夫| 最新黄色免费网站| 亚洲av中文无码乱人伦在线播放 |