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

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

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

    鷹翔宇空

    學習和生活

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks
    原文引自:http://www-128.ibm.com/developerworks/cn/java/j-jstl0318/index.html

    顧名思義,JSP 標準標記庫(JSP Standard Tag Library,JSTL) core 庫為一些基本功能(如,管理限定了作用域的變量和與 URL 交互等)和基本操作(如,迭代和條件化)提供了定制標記。這些標記不僅可以由頁面設計人員直接利用,而且還為與其它 JSTL 庫相結合從而提供更復雜的表示邏輯奠定了基礎。Mark Kolb 在本文中繼續對 JSTL 和 core 庫進行探討,研究用標記來協助流控制和 URL 管理。

    通過閱讀本系列的 第一篇文章,您對 JSTL 有了初步的了解。我們描述了使用其 表達式語言(EL)來訪問數據和操作數據。正如您所了解的那樣,EL 用來為 JSTL 定制標記的屬性賦予動態值,因此,它所起的作用與 JSP 表達式一樣,為內置操作及其它定制標記庫指定請求時的屬性值。

    為了演示 EL 的用法,我們介紹了 core 庫中的三個標記: <c:set><c:remove><c:out><c:set><c:remove> 用于管理限定了作用域的變量;而 <c:out> 用于顯示數據,尤其是顯示用 EL 計算出的值。在此基礎上,接下來本文把注意力集中在 core 庫的其余標記上,這些標記可以大致歸為兩大類別:流控制和 URL 管理。

    示例應用程序

    為了演示 JSTL 標記,我們將使用來自一個工作應用程序的示例,本系列中余下的文章都將使用此應用程序。由于基于 Java 的 Weblog 日漸流行及為人們所熟悉,因此我們將出于此目的使用一個簡單的基于 Java 的 Weblog;參閱 參考資料以下載該應用程序的 JSP 頁面和源代碼。Weblog(也稱為 blog)是一種基于 Web 的簡短注釋的日志,這些注釋是有關 Weblog 的作者所感興趣的主題,通常帶有與 Web 上其它地方的相關文章及討論的鏈接。圖 1 中顯示了該應用程序正在運行時的抓屏。


    圖 1. Weblog 應用程序
    Weblog 示例應用程序的抓屏

    雖然完整的實現需要二十四個 Java 類,但在表示層中卻只涉及 Weblog 應用程序中的兩個類, EntryUserBean 。這樣,對于理解 JSTL 示例而言,只有這兩個類比較重要。圖 2 顯示了 EntryUserBean 的類圖。


    圖 2. Weblog 應用程序的類圖
    Weblog 示例應用程序的類圖

    Entry 類表示 Weblog 中一個標有日期的項。其 id 屬性用于在數據庫中存儲及檢索該項,而 titletext 屬性則表示該項的實際內容。 createdlastModified 屬性引用了 Java 語言中 Date 類的兩個實例,分別用來表示最初創建該項的時間和最后編輯該項的時間。 author 屬性引用了標識該項的創建者的 UserBean 實例。

    UserBean 類存儲了有關應用程序的已認證用戶的信息,如用戶名、全名和電子郵件地址。該類還包含一個用于與相關數據庫進行交互的 id 屬性。其最后一個屬性 roles 引用一列 String 值,這列值標識與相應用戶相關的、特定于應用程序的角色。對于 Weblog 應用程序,相關的角色是“User”(所有應用程序用戶常用的缺省角色)和“Author”(該角色指定可以創建和編輯 Weblog 項的用戶)。





    回頁首


    流控制

    由于可以用 EL 替代 JSP 表達式來指定動態屬性值,因此頁面創作人員無需使用腳本編制元素。因為腳本編制元素可能是引起 JSP 頁面中維護問題的主要原因,所以 JSTL 的主要優點就在于提供了這樣簡單(且標準)的替代方法。

    EL 從 JSP 容器檢索數據,遍歷對象層次結構,然后對結果執行簡單的操作。不過,除了訪問和操作數據之外,JSP 腳本編制元素的另一個常見用法是流控制。尤其是,頁面創作人員常借助 scriptlet 來實現迭代或條件內容。然而,因為這樣的操作超出了 EL 的能力,所以 core 庫提供了幾個定制操作來管理流控制,其形式有 迭代條件化異常處理

    迭代

    在 Web 應用程序環境中,迭代主要用于訪存和顯示數據集,通常是以列表或表中的一系列行的形式顯示。實現迭代內容的主要 JSTL 操作是 <c:forEach> 定制標記。該標記支持兩種不同樣式的迭代:整數范圍上的迭代(類似 Java 語言的 for 語句)和集合上的迭代(類似 Java 語言的 IteratorEnumeration 類)。

    進行整數范圍迭代用到了清單 1 中所示的 <c:forEach> 標記的語法。 beginend 屬性要么是靜態整數值,要么是可以得出整數值的表達式。它們分別指定迭代索引的初始值以及迭代索引的終止值。當使用 <c:forEach> 在整數范圍內進行迭代時,這兩個屬性是必需的,而其它所有屬性都是可選的。


    清單 1. 通過 <c:forEach> 操作進行數字迭代的語法
    <c:forEach var="
            name" varStatus="
            name"
        begin="
            expression" end="
            expression" step="
            expression">
      
            body content
    </c:forEach>
    
          

    當出現 step 時,它也必須是整數值。它指定每次迭代后索引的增量。這樣,迭代索引從 begin 屬性的值開始,以 step 屬性的值為增量進行遞增,在迭代索引超過 end 屬性的值時停止迭代。注:如果省略了 step 屬性,那么步長缺省為 1。

    如果指定了 var 屬性,那么將會創建一個帶有指定名稱的并限定了作用域的變量,并將每次迭代的當前索引值賦給該變量。這一限定了作用域的變量具有嵌套式可視性 ― 只可以在 <c:forEach> 標記體內對其進行訪問。(我們很快將討論可選屬性 varStatus 的用法。)清單 2 顯示了對一組固定整數值進行迭代的 <c:forEach> 操作示例。


    清單 2. 使用 <c:forEach> 標記來生成表列數據,這些數據對應于某一范圍內的數值
    <table>
    <tr><th>Value</th>
        <th>Square</th></tr>
    <c:forEach var="x" begin="0" end="10" step="2">
      <tr><td><c:out value="${x}"/></td>
          <td><c:out value="${x * x}"/></td></tr>
    </c:forEach>
    </table>
    

    如圖 3 中所示,上面的示例代碼生成了一張表,顯示前五個偶數及其平方。這是通過將 beginstep 屬性值指定為 2,而將 end 屬性值指定為 10 實現的。此外,用 var 屬性創建用于存儲索引值的限定了作用域的變量, <c:forEach> 標記體內引用了該變量。尤其是,使用了一對 <c:out> 操作來顯示索引及其平方,其中索引的平方是使用一個簡單的表達式計算得來的。


    圖 3. 清單 2 的輸出
    清單 2 的輸出

    在對集合的成員進行迭代時,用到了 <c:forEach> 標記的另一個屬性: items 屬性,清單 3 中顯示了該屬性。當使用這種形式的 <c:forEach> 標記時, items 屬性是唯一必需的屬性。 items 屬性的值應該是一個集合,對該集合的成員進行迭代,通常使用 EL 表達式指定值。如果變量名稱是通過 <c:forEach> 標記的 item 屬性指定的,那么對于每次迭代該已命名變量都將被綁定到集合后續元素上。


    清單 3. 通過 <c:forEach> 操作對集合進行迭代的語法
    <c:forEach var="
            name" items="
            expression" varStatus="
            name"
        begin="
            expression" end="
            expression" step="
            expression">
      
            body content
    </c:forEach>
    
          

    <c:forEach> 標記支持 Java 平臺所提供的所有標準集合類型。此外,您可以使用該操作來迭代數組(包括基本類型數組)中的元素。表 1 列出了 items 屬性所支持的所有值。正如表的最后一行所指出的那樣,JSTL 定義了它自己的接口 javax.servlet.jsp.jstl.sql.Result ,用來迭代 SQL 查詢的結果。(我們將在本系列后面的文章中詳細討論這一功能。)

    表 1. <c:forEach> 標記的 items 屬性所支持的集合

    items 的值 所產生的 item
    java.util.Collection調用 iterator() 所獲得的元素
    java.util.Mapjava.util.Map.Entry 的實例
    java.util.Iterator迭代器元素
    java.util.Enumeration枚舉元素
    Object 實例數組 數組元素
    基本類型值數組經過包裝的數組元素
    用逗號定界的 String子字符串
    javax.servlet.jsp.jstl.sql.ResultSQL 查詢所獲得的行

    可以使用 beginendstep 屬性來限定在迭代中包含集合中哪些元素。和通過 <c:forEach> 進行數字迭代的情形一樣,在迭代集合中的元素時同樣要維護一個迭代索引。 <c:forEach> 標記實際上只處理那些與索引值相對應的元素,這些索引值與指定的 beginendstep 值相匹配。

    清單 4 顯示了用來迭代集合的 <c:forEach> 標記。對于該 JSP 代碼段, entryList 這一限定了作用域的變量被設置成了 Entry 對象列表(確切的說, ArrayList )。 <c:forEach> 標記依次處理列表中的每個元素,將其賦給一個限定了作用域的變量 blogEntry ,然后生成兩個表行 ― 一個用于 Weblog 項的 title ,另一個則用于該項 text 。這些特性是通過一對帶有相應 EL 表達式的 <c:out> 操作從 blogEntry 變量檢索得到的。注:由于 Weblog 項的標題和文本都可能包含 HTML 標記,因此這兩個 <c:out> 標記的 escapeXml 屬性都被設置成了 false。圖 4 顯示了結果。


    清單 4. 使用 <c:forEach> 標記顯示表示給定日期的 Weblog 項
    <table>
      <c:forEach items="${entryList}" var="blogEntry">
        <tr><td align="left" class="blogTitle">
          <c:out value="${blogEntry.title}" escapeXml="false"/>
        </td></tr>
        <tr><td align="left" class="blogText">
          <c:out value="${blogEntry.text}" escapeXml="false"/>
        </td></tr>
      </c:forEach>
    </table>
    


    圖 4. 清單 4 的輸出
    清單 4 的輸出

    不論是對整數還是對集合進行迭代, <c:forEach> 剩余的屬性 varStatus 所起的作用相同。和 var 屬性一樣, varStatus 用于創建限定了作用域的變量。不過,由 varStatus 屬性命名的變量并不存儲當前索引值或當前元素,而是賦予 javax.servlet.jsp.jstl.core.LoopTagStatus 類的實例。該類定義了一組特性,它們描述了迭代的當前狀態,表 2 中列出了這些特性。

    表 2. LoopTagStatus 對象的特性

    特性Getter描述
    currentgetCurrent()當前這次迭代的(集合中的)項
    indexgetIndex()當前這次迭代從 0 開始的迭代索引
    countgetCount()當前這次迭代從 1 開始的迭代計數
    firstisFirst()用來表明當前這輪迭代是否為第一次迭代的標志
    lastisLast()用來表明當前這輪迭代是否為最后一次迭代的標志
    begingetBegin()begin 屬性值
    endgetEnd()end 屬性值
    stepgetStep()step 屬性值

    清單 5 顯示了關于如何使用 varStatus 屬性的一個示例。這個示例修改了清單 4 中的代碼,將 Weblog 項的編號添加到顯示 Weblog 標題(title)的表行。它是通過為 varStatus 屬性指定一個值,然后訪問所生成的限定了作用域的變量的 count 特性來實現這一點的。結果顯示在圖 5 中。


    清單 5. 使用 varStatus 屬性來顯示 Weblog 項的數目
    <table>
      <c:forEach items=
        "${entryList}" var="blogEntry" varStatus="status">
        <tr><td align="left" class="blogTitle">
          <c:out value="${status.count}"/>.
          <c:out value="${blogEntry.title}" escapeXml="false"/>
        </td></tr>
        <tr><td align="left" class="blogText">
          <c:out value="${blogEntry.text}" escapeXml="false"/>
        </td></tr>
      </c:forEach>
    </table>
    


    圖 5. 清單 5 的輸出
    清單 5 的輸出

    <c:forEach> 以外, core 庫還提供了另一個迭代標記: <c:forTokens> 。JSTL 的這個定制操作與 Java 語言的 StringTokenizer 類的作用相似。清單 6 中顯示的 <c:forTokens> 標記除了比 <c:forEach> 的面向集合版本多一個屬性之外,其它屬性都相同。對于 <c:forTokens> 而言,通過 items 屬性指定要標記化的字符串,而通過 delims 屬性提供用于生成標記的一組定界符。和 <c:forEach> 的情形一樣,可以使用 beginendstep 屬性將要處理的標記限定為那些與相應索引值相匹配的標記。


    清單 6. 使用 <c:forTokens> 操作來迭代字符串標記的語法
    <c:forTokens var="
            name" items="
            expression"
        delims="
            expression" varStatus="
            name"
        begin="
            expression" end="
            expression" step="
            expression">
      
            body content
    </c:forTokens>
    
          

    條件化

    對于包含動態內容的 Web 頁面,您可能希望不同類別的用戶看到不同形式的內容。例如,在我們的 Weblog 中,訪問者應該能夠閱讀各項,也許還應該能夠提交反饋,但只有經過授權的用戶才能公布新項,或編輯已有內容。

    在同一個 JSP 頁面內實現這樣的功能,然后使用條件邏輯來根據每條請求控制所顯示的內容,這樣做常常能夠改善實用性和軟件維護。 core 庫提供了兩個不同的條件化標記 ― <c:if><c:choose> ― 來實現這些功能。

    <c:if> 是這兩個操作中較簡單的一個,它簡單地對單個測試表達式進行求值,接下來,僅當對表達式求出的值為 true 時,它才處理標記的主體內容。如果求出的值不為 true ,就忽略該標記的主體內容。如清單 7 所示, <c:if> 可以通過其 varscope 屬性(它們所起的作用和在 <c:set> 中所起的作用一樣)選擇將測試結果賦給限定了作用域的變量。當測試代價非常高昂時,這種能力尤為有用:可以將結果高速緩存在限定了作用域的變量中,然后在隨后對 <c:if> 或其它 JSTL 標記的調用中檢索該結果。


    清單 7. <c:if> 條件操作的語法
    <c:if test="
            expression" var="
            name" scope="
            scope">
      
            body content
    </c:if>
    
          

    清單 8 顯示了與 <c:forEach> 標記的 LoopTagStatus 對象的 first 特性一起使用的 <c:if> 。如圖 6 中所示,在這種情況下,只在 Weblog 項的第一項上顯示這組項的創建日期,而不在任何其它項前面重復該日期。


    清單 8. 使用 <c:if> 來為 Weblog 項顯示日期
    <table>
      <c:forEach items=
        "${entryList}" var="blogEntry" varStatus="status">
        <c:if test="${status.first}">
          <tr><td align="left" class="blogDate">
                <c:out value="${blogEntry.created}"/>
          </td></tr>
        </c:if>
        <tr><td align="left" class="blogTitle">
          <c:out value="${blogEntry.title}" escapeXml="false"/>
        </td></tr>
        <tr><td align="left" class="blogText">
          <c:out value="${blogEntry.text}" escapeXml="false"/>
        </td></tr>
      </c:forEach>
    </table>
    


    圖 6. 清單 8 的輸出
    清單 8 的輸出

    如清單 8 所示, <c:if> 標記為條件化內容的一些簡單情形提供了一種非常簡潔的表示法。對于需要進行互斥測試來確定應該顯示什么內容的情況下,JSTL core 庫還提供了 <c:choose> 操作。清單 9 中顯示了 <c:choose> 的語法。


    清單 9. <c:choose> 操作的語法
    <c:choose>
      <c:when test="
            expression">
        
            body content
      </c:when>
      ...
      <c:otherwise>
        
            body content
      </c:otherwise>
    </c:choose>
    
          

    每個要測試的條件都由相應的 <c:when> 標記來表示,至少要有一個 <c:when> 標記。只會處理第一個其 test 值為 true<c:when> 標記體內的內容。如果沒有一個 <c:when> 測試返回 true ,那么會處理 <c:otherwise> 標記的主體內容。注:盡管如此, <c:otherwise> 標記卻是可選的; <c:choose> 標記至多可有一個嵌套的 <c:otherwise> 標記。如果所有 <c:when> 測試都為 false ,而且又沒有給出 <c:otherwise> 操作,那么不會處理任何 <c:choose> 標記的主體內容。

    清單 10 顯示了運用 <c:choose> 標記的示例。在這里,檢索請求對象而獲得協議信息(通過 EL 的 pageContext 隱式對象),并用簡單的字符串比較對協議信息進行測試。根據這些測試的結果,會顯示相應的文本消息。


    清單 10. 使用 <c:choose> 進行內容條件化
    <c:choose>
      <c:when test="${pageContext.request.scheme eq 'http'}">
        This is an insecure Web session.
      </c:when>
      <c:when test="${pageContext.request.scheme eq 'https'}">
        This is a secure Web session.
      </c:when>
      <c:otherwise>
        You are using an unrecognized Web protocol. How did this happen?!
      </c:otherwise>
    </c:choose>
    

    異常處理

    最后一個流控制標記是 <c:catch> ,它允許在 JSP 頁面內進行初級的異常處理。更確切地說,在該標記的主體內容中產生的任何異常都會被捕獲并被忽略(即,不會調用標準的 JSP 錯誤處理機制)。然而,如果產生了一個異常并且已經指定了 <c:catch> 標記的可選屬性 var ,那么會將異常賦給(具有頁面作用域的)指定的變量,這使得能夠在頁面自身內部進行定制錯誤處理。清單 11 顯示了 <c:catch> 的語法(稍后在 清單 18中給出一個示例)。


    清單 11. <c:catch> 操作的語法
    <c:catch var="
            name">
      
            body content
    </c:catch>
    
          





    回頁首


    URL 操作

    JSTL core 庫中的其余標記主要是關于 URL。這些標記中的第一個被適當地命名為 <c:url> 標記,用于生成 URL。尤其是, <c:url> 提供了三個功能元素,它們在為 J2EE Web 應用程序構造 URL 時特別有用:

    • 在前面附加當前 servlet 上下文的名稱
    • 為會話管理重寫 URL
    • 請求參數名稱和值的 URL 編碼

    清單 12 顯示了 <c:url> 標記的語法。 value 屬性用來指定基本 URL,然后在必要時標記對其進行轉換。如果這個基本 URL 以一個斜杠開始,那么會在它前面加上 servlet 的上下文名稱。可以使用 context 屬性提供顯式的上下文名稱。如果省略該屬性,那么就使用當前 servlet 上下文的名稱。這一點特別有用,因為 servlet 上下文名稱是在部署期間而不是開發期間決定的。(如果這個基本 URL 不是以斜杠開始的,那么就認為它是一個相對 URL,這時就不必添加上下文名稱。)


    清單 12. <c:url> 操作的語法
    <c:url value="
            expression" context="
            expression"
        var="
            name" scope="
            scope">
      <c:param name="
            expression" value="
            expression"/>
      ...
    </c:url>
    
          

    URL 重寫是由 <c:url> 操作自動執行的。如果 JSP 容器檢測到一個存儲用戶當前會話標識的 cookie,那么就不必進行重寫。但是,如果不存在這樣的 cookie,那么 <c:url> 生成的所有 URL 都會被重寫以編碼會話標識。注:如果在隨后的請求中存在適當的 cookie,那么 <c:url> 將停止重寫 URL 以包含該標識。

    如果為 var 屬性提供了一個值(還可以同時為 scope 屬性提供一個相應的值,這是可選的),那么將生成的 URL 賦值給這個限定了作用域的指定變量。否則,將使用當前的 JspWriter 輸出生成的 URL。這種直接輸出其結果的能力允許 <c:url> 標記作為值出現,例如,作為 HTML <a> 標記的 href 屬性的值,如清單 13 中所示。


    清單 13. 生成 URL 作為 HTML 標記的屬性值
    <a href="<c:url value='/content/sitemap.jsp'/>">View sitemap</a>
    

    最后,如果通過嵌套 <c:param> 標記指定了任何請求參數,那么將會使用 HTTP GET 請求的標準表示法將它們的名稱和值添加到生成的 URL 后面。此外,還進行 URL 編碼:為了生成有效的 URL,將對這些參數的名稱或值中出現的任何字符適當地進行轉換。清單 14 演示了 <c:url> 的這種行為。


    清單 14. 生成帶請求參數的 URL
    <c:url value="/content/search.jsp">
      <c:param name="keyword" value="${searchTerm}"/>
      <c:param name="month" value="02/2003"/>
    </c:url>
    

    清單 14 中的 JSP 代碼被部署到一個名為 blog 的 servlet 上下文,限定了作用域的變量 searchTerm 的值被設置為 "core library" 。如果檢測到了會話 cookie,那么清單 14 生成的 URL 將類似于清單 15 中的 URL。注:在前面添加上下文名稱,而在后面附加請求參數。此外, keyword 參數值中的空格和 month 參數值中的斜杠都被按照 HTTP GET 參數的需要進行了編碼(確切地說,空格被轉換成了 + ,而斜杠被轉換成了 %2F 序列)。


    清單 15. 有會話 cookie 時生成的 URL
    /blog/content/search.jsp?keyword=foo+bar&month=02%2F2003
    

    當沒有會話 cookie 時,生成的結果如清單 16 中所示。同樣,servlet 上下文被添加到了前面,而 URL 編碼的請求參數被附加到了后面。不過,除此以外還重寫了基本 URL 以包含指定的會話標識。當瀏覽器發送用這種方式重寫的 URL 請求時,JSP 容器自動抽取會話標識,并將請求與相應的會話進行關聯。這樣,需要會話管理的 J2EE 應用程序就無需依賴由應用程序用戶啟用的 cookie 了。


    清單 16. 沒有會話 cookie 時生成的 URL
    /blog/content/search.jsp;jsessionid=233379C7CD2D0ED2E9F3963906DB4290
      ?keyword=foo+bar&month=02%2F2003
    





    回頁首


    導入內容

    JSP 有兩種內置機制可以將來自不同 URL 的內容合并到一個 JSP 頁面: include 偽指令和 <jsp:include> 操作。不過,不管是哪種機制,要包含的內容都必須屬于與頁面本身相同的 Web 應用程序(或 servlet 上下文)。兩個標記之間的主要區別在于: include 偽指令在頁面編譯期間合并被包含的內容,而 <jsp:include> 操作卻在請求處理 JSP 頁面時進行。

    從本質上講, core 庫的 <c:import> 操作是更通用、功能更強大的 <jsp:include> 版本(好像是 <jsp:include> “服用了興奮劑”的)。和 <jsp:include> 一樣, <c:import> 也是一種請求時操作,它的基本任務就是將其它一些 Web 資源的內容插入 JSP 頁面中。如清單 17 中所示,它的語法非常類似于 <c:url> 的語法。


    清單 17. <c:import> 操作的語法
    <c:import url="
            expression" context="
            expression"
        charEncoding="
            expression" var="
            name" scope="
            scope">
      <c:param name="
            expression" value="
            expression"/>
      ...
    </c:import>
    
          

    通過 url 屬性指定將要導入內容的 URL,這個屬性是 <c:import> 的唯一一個必選屬性。這里允許使用相對 URL,并且根據當前頁面的 URL 來解析這個相對 URL。但是,如果 url 屬性的值以斜杠開始,那么它就被解釋成本地 JSP 容器內的絕對 URL。如果沒有為 context 屬性指定值,那么就認為這樣的絕對 URL 引用當前 servlet 上下文內的資源。如果通過 context 屬性顯式地指定了上下文,那么就根據指定的 servlet 上下文解析絕對(本地)URL。

    <c:import> 操作并不僅僅限于訪問本地內容。也可以將包含協議和主機名的完整 URI 指定為 url 屬性的值。實際上,協議甚至不僅局限于 HTTP。 <c:import>url 屬性值可以使用 java.net.URL 類所支持的任何協議。清單 18 中顯示了這種能力。

    其中, <c:import> 操作用來包含通過 FTP 協議訪問的文檔內容。此外,還使用了 <c:catch> 操作,以便在本地處理 FTP 文件傳送期間可能發生的任何錯誤。錯誤處理是這樣實現的:使用 <c:catch>var 屬性為異常指定一個限定了作用域的變量,然后使用 <c:if> 檢查其值。如果產生了異常,那么就會對那個限定了作用域的變量進行賦值:如清單 18 中的 EL 表達式所顯示的那樣,該變量的值將 會為空。由于 FTP 文檔的檢索將會失敗,因此會顯示有關這種情況的錯誤消息。


    清單 18. 將 <c:import> 與 <c:catch> 相結合的示例
    <c:catch var="exception">
      <c:import url="ftp://ftp.example.com/package/README"/>
    </c:catch>
    <c:if test="${not empty exception}">
      Sorry, the remote content is not currently available.
    </c:if>
    

    <c:import> 操作的最后兩個(可選的)屬性是 varscopevar 屬性會導致從指定 URL 獲取的內容(作為 String 值)被存儲在一個限定了作用域的變量中,而不是包含在當前 JSP 頁面中。 scope 屬性控制該變量的作用域,缺省情況下是頁面作用域。如同我們在今后的文章中將要看到的那樣,JSTL xml 庫中的標記利用了 <c:import> 這種能力,即將整個文檔存儲在一個限定了作用域的變量中。

    還要注意的是,可以使用(可選的)嵌套的 <c:param> 標記來為正在導入的 URL 指定請求參數。與在 <c:url> 中嵌套 <c:param> 標記一樣,必要時也要對參數名稱和參數值進行 URL 編碼。





    回頁首


    請求重定向

    最后一個 core 庫標記是 <c:redirect> 。該操作用于向用戶的瀏覽器發送 HTTP 重定向響應,它是 JSTL 中與 javax.servlet.http.HttpServletResponsesendRedirect() 方法功能相當的標記。清單 19 中顯示了該標記的 urlcontext 屬性,它們的行為分別等同于 <c:import>urlcontext 屬性的行為,是嵌套任何 <c:param> 標記的結果。


    清單 19. <c:redirect> 操作的語法
    <c:redirect url="
            expression" context="
            expression">
      <c:param name="
            expression" value="
            expression"/>
      ...
    </c:redirect>
    
          

    清單 20 顯示了 <c:redirect> 操作,它用一個到指定錯誤頁面的重定向代替了清單 18 中的錯誤消息。在該示例中, <c:redirect> 標記的用法與標準 <jsp:forward> 操作的用法類似。不過請回憶一下:通過請求分派器進行轉發是在服務器端實現的,而重定向卻是由瀏覽器來執行的。從開發人員的角度來講,轉發比重定向更有效率,但 <c:redirect> 操作卻更靈活一些,因為 <jsp:forward> 只能分派到當前 servlet 上下文內的其它 JSP 頁面。


    清單 20. 響應異常的重定向
    <c:catch var="exception">
      <c:import url="ftp://ftp.example.com/package/README"/>
    </c:catch>
    <c:if test="${not empty exception}">
      <c:redirect url="/errors/remote.jsp"/>
    </c:if>
    

    從用戶的角度來看,主要區別在于重定向會更新瀏覽器所顯示的 URL,并因此影響書簽的設置。轉發卻不這樣,它對最終用戶是透明的。這樣,選擇 <c:redirect> 還是 <jsp:forward> 還取決于所期望的用戶體驗。





    回頁首


    結束語

    JSTL core 庫含有多種通用的定制標記,廣大的 JSP 開發人員都會使用這些標記。例如,URL 和異常處理標記很好地補充了現有的 JSP 功能,如 <jsp:include><jsp:forward> 操作、 include 偽指令以及 page 偽指令的 errorpage 屬性。迭代和條件操作使得無需腳本編制元素就能夠實現復雜的表示邏輯,尤其在將變量標記( <c:set><c:remove> )與 EL 相結合使用時更是如此。





    回頁首


    參考資料





    回頁首


    關于作者

    Mark Kolb 是一位在德克薩斯州奧斯汀市(Austin)工作的軟件工程師。他常就服務器端 Java 這一主題在業界演講,而且還是 Web Development with JavaServer Pages, 第二版一書的合著者。可以通過 mak@taglib.com與 Mark 聯系。

    posted on 2006-05-16 12:33 TrampEagle 閱讀(579) 評論(0)  編輯  收藏 所屬分類: web
    主站蜘蛛池模板: 亚洲国产精品日韩在线| 亚洲专区在线视频| 亚洲AV无码XXX麻豆艾秋| 妞干网手机免费视频| 亚洲1234区乱码| 无码高潮少妇毛多水多水免费| 亚洲va成无码人在线观看| 三年片在线观看免费大全 | 亚洲国产精品无码久久久秋霞1| 全免费毛片在线播放| 亚洲成人激情小说| 免费高清av一区二区三区| 亚洲AV成人无码网天堂| 亚洲国产精品成人| 中文字幕免费在线看| 亚洲天堂男人天堂| 最近中文字幕无吗免费高清| 国产AV无码专区亚洲AV蜜芽| 亚洲区不卡顿区在线观看| 精品熟女少妇aⅴ免费久久| 久久亚洲精品成人777大小说| 99久久精品免费视频| 亚洲伊人久久大香线蕉AV| 国产免费观看青青草原网站| 九九久久精品国产免费看小说 | 青青久在线视频免费观看| 亚洲精品精华液一区二区 | 久青草国产免费观看| 亚洲一区二区三区电影| 日韩免费视频观看| a级毛片在线免费| 亚洲深深色噜噜狠狠网站| 亚洲人成国产精品无码| 91精品国产免费久久国语麻豆| 亚洲熟妇少妇任你躁在线观看| 亚洲国产精品尤物YW在线观看| 免费播放在线日本感人片| 麻豆狠色伊人亚洲综合网站 | 精品久久久久久无码免费| 亚洲视频中文字幕在线| 免费一级毛片清高播放|