顧名思義,JSP 標準標記庫(JSP Standard Tag Library,JSTL)core庫為一些基本功能(如,管理限定了作用域的變量和與 URL 交互等)和基本操作(如,迭代和條件化)提供了定制標記。這些標記不僅可以由頁(yè)面設計人員直接利用,而且還為與其它 JSTL 庫相結合從而提供更復雜的表示邏輯奠定了基礎。Mark Kolb 在本文中繼續對 JSTL 和core庫進(jìn)行探討,研究用標記來(lái)協(xié)助流控制和 URL 管理。
通過(guò)閱讀本系列的 第一篇文章,您對 JSTL 有了初步的了解。我們描述了使用其 表達式語(yǔ)言(EL)來(lái)訪(fǎng)問(wèn)數據和操作數據。正如您所了解的那樣,EL 用來(lái)為 JSTL 定制標記的屬性賦予動(dòng)態(tài)值,因此,它所起的作用與 JSP 表達式一樣,為內置操作及其它定制標記庫指定請求時(shí)的屬性值。
為了演示 EL 的用法,我們介紹了 core 庫中的三個(gè)標記: <c:set> 、 <c:remove> 和 <c:out> 。 <c:set> 和 <c:remove> 用于管理限定了作用域的變量;而 <c:out> 用于顯示數據,尤其是顯示用 EL 計算出的值。在此基礎上,接下來(lái)本文把注意力集中在 core 庫的其余標記上,這些標記可以大致歸為兩大類(lèi)別:流控制和 URL 管理。
為了演示 JSTL 標記,我們將使用來(lái)自一個(gè)工作應用程序的示例,本系列中余下的文章都將使用此應用程序。由于基于 Java 的 Weblog 日漸流行及為人們所熟悉,因此我們將出于此目的使用一個(gè)簡(jiǎn)單的基于 Java 的 Weblog;參閱 參考資料以下載該應用程序的 JSP 頁(yè)面和源代碼。Weblog(也稱(chēng)為 blog)是一種基于 Web 的簡(jiǎn)短注釋的日志,這些注釋是有關(guān) Weblog 的作者所感興趣的主題,通常帶有與 Web 上其它地方的相關(guān)文章及討論的鏈接。圖 1 中顯示了該應用程序正在運行時(shí)的抓屏。

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

Entry 類(lèi)表示 Weblog 中一個(gè)標有日期的項。其 id 屬性用于在數據庫中存儲及檢索該項,而 title 和 text 屬性則表示該項的實(shí)際內容。 created 和 lastModified 屬性引用了 Java 語(yǔ)言中 Date 類(lèi)的兩個(gè)實(shí)例,分別用來(lái)表示最初創(chuàng )建該項的時(shí)間和最后編輯該項的時(shí)間。 author 屬性引用了標識該項的創(chuàng )建者的 UserBean 實(shí)例。
UserBean 類(lèi)存儲了有關(guān)應用程序的已認證用戶(hù)的信息,如用戶(hù)名、全名和電子郵件地址。該類(lèi)還包含一個(gè)用于與相關(guān)數據庫進(jìn)行交互的 id 屬性。其最后一個(gè)屬性 roles 引用一列 String 值,這列值標識與相應用戶(hù)相關(guān)的、特定于應用程序的角色。對于 Weblog 應用程序,相關(guān)的角色是“User”(所有應用程序用戶(hù)常用的缺省角色)和“Author”(該角色指定可以創(chuàng )建和編輯 Weblog 項的用戶(hù))。
![]() ![]() |
![]()
|
由于可以用 EL 替代 JSP 表達式來(lái)指定動(dòng)態(tài)屬性值,因此頁(yè)面創(chuàng )作人員無(wú)需使用腳本編制元素。因為腳本編制元素可能是引起 JSP 頁(yè)面中維護問(wèn)題的主要原因,所以 JSTL 的主要優(yōu)點(diǎn)就在于提供了這樣簡(jiǎn)單(且標準)的替代方法。
EL 從 JSP 容器檢索數據,遍歷對象層次結構,然后對結果執行簡(jiǎn)單的操作。不過(guò),除了訪(fǎng)問(wèn)和操作數據之外,JSP 腳本編制元素的另一個(gè)常見(jiàn)用法是流控制。尤其是,頁(yè)面創(chuàng )作人員常借助 scriptlet 來(lái)實(shí)現迭代或條件內容。然而,因為這樣的操作超出了 EL 的能力,所以 core 庫提供了幾個(gè)定制操作來(lái)管理流控制,其形式有 迭代、 條件化和 異常處理。
在 Web 應用程序環(huán)境中,迭代主要用于訪(fǎng)存和顯示數據集,通常是以列表或表中的一系列行的形式顯示。實(shí)現迭代內容的主要 JSTL 操作是 <c:forEach> 定制標記。該標記支持兩種不同樣式的迭代:整數范圍上的迭代(類(lèi)似 Java 語(yǔ)言的 for 語(yǔ)句)和集合上的迭代(類(lèi)似 Java 語(yǔ)言的 Iterator 和 Enumeration 類(lèi))。
進(jìn)行整數范圍迭代用到了清單 1 中所示的 <c:forEach> 標記的語(yǔ)法。 begin 和 end 屬性要么是靜態(tài)整數值,要么是可以得出整數值的表達式。它們分別指定迭代索引的初始值以及迭代索引的終止值。當使用 <c:forEach> 在整數范圍內進(jìn)行迭代時(shí),這兩個(gè)屬性是必需的,而其它所有屬性都是可選的。
|
當出現 step 時(shí),它也必須是整數值。它指定每次迭代后索引的增量。這樣,迭代索引從 begin 屬性的值開(kāi)始,以 step 屬性的值為增量進(jìn)行遞增,在迭代索引超過(guò) end 屬性的值時(shí)停止迭代。注:如果省略了 step 屬性,那么步長(cháng)缺省為 1。
如果指定了 var 屬性,那么將會(huì )創(chuàng )建一個(gè)帶有指定名稱(chēng)的并限定了作用域的變量,并將每次迭代的當前索引值賦給該變量。這一限定了作用域的變量具有嵌套式可視性 ― 只可以在 <c:forEach> 標記體內對其進(jìn)行訪(fǎng)問(wèn)。(我們很快將討論可選屬性 varStatus 的用法。)清單 2 顯示了對一組固定整數值進(jìn)行迭代的 <c:forEach> 操作示例。
|
如圖 3 中所示,上面的示例代碼生成了一張表,顯示前五個(gè)偶數及其平方。這是通過(guò)將 begin 和 step 屬性值指定為 2,而將 end 屬性值指定為 10 實(shí)現的。此外,用 var 屬性創(chuàng )建用于存儲索引值的限定了作用域的變量, <c:forEach> 標記體內引用了該變量。尤其是,使用了一對 <c:out> 操作來(lái)顯示索引及其平方,其中索引的平方是使用一個(gè)簡(jiǎn)單的表達式計算得來(lái)的。

在對集合的成員進(jìn)行迭代時(shí),用到了 <c:forEach> 標記的另一個(gè)屬性: items 屬性,清單 3 中顯示了該屬性。當使用這種形式的 <c:forEach> 標記時(shí), items 屬性是唯一必需的屬性。 items 屬性的值應該是一個(gè)集合,對該集合的成員進(jìn)行迭代,通常使用 EL 表達式指定值。如果變量名稱(chēng)是通過(guò) <c:forEach> 標記的 item 屬性指定的,那么對于每次迭代該已命名變量都將被綁定到集合后續元素上。
|
<c:forEach> 標記支持 Java 平臺所提供的所有標準集合類(lèi)型。此外,您可以使用該操作來(lái)迭代數組(包括基本類(lèi)型數組)中的元素。表 1 列出了 items 屬性所支持的所有值。正如表的最后一行所指出的那樣,JSTL 定義了它自己的接口 javax.servlet.jsp.jstl.sql.Result ,用來(lái)迭代 SQL 查詢(xún)的結果。(我們將在本系列后面的文章中詳細討論這一功能。)
表 1. <c:forEach> 標記的 items 屬性所支持的集合
items 的值 | 所產(chǎn)生的 item 值 |
java.util.Collection | 調用 iterator() 所獲得的元素 |
java.util.Map | java.util.Map.Entry 的實(shí)例 |
java.util.Iterator | 迭代器元素 |
java.util.Enumeration | 枚舉元素 |
Object 實(shí)例數組 | 數組元素 |
| 基本類(lèi)型值數組 | 經(jīng)過(guò)包裝的數組元素 |
用逗號定界的 String | 子字符串 |
javax.servlet.jsp.jstl.sql.Result | SQL 查詢(xún)所獲得的行 |
可以使用 begin 、 end 和 step 屬性來(lái)限定在迭代中包含集合中哪些元素。和通過(guò) <c:forEach> 進(jìn)行數字迭代的情形一樣,在迭代集合中的元素時(shí)同樣要維護一個(gè)迭代索引。 <c:forEach> 標記實(shí)際上只處理那些與索引值相對應的元素,這些索引值與指定的 begin 、 end 和 step 值相匹配。
清單 4 顯示了用來(lái)迭代集合的 <c:forEach> 標記。對于該 JSP 代碼段, entryList 這一限定了作用域的變量被設置成了 Entry 對象列表(確切的說(shuō), ArrayList )。 <c:forEach> 標記依次處理列表中的每個(gè)元素,將其賦給一個(gè)限定了作用域的變量 blogEntry ,然后生成兩個(gè)表行 ― 一個(gè)用于 Weblog 項的 title ,另一個(gè)則用于該項 text 。這些特性是通過(guò)一對帶有相應 EL 表達式的 <c:out> 操作從 blogEntry 變量檢索得到的。注:由于 Weblog 項的標題和文本都可能包含 HTML 標記,因此這兩個(gè) <c:out> 標記的 escapeXml 屬性都被設置成了 false。圖 4 顯示了結果。
|

不論是對整數還是對集合進(jìn)行迭代, <c:forEach> 剩余的屬性 varStatus 所起的作用相同。和 var 屬性一樣, varStatus 用于創(chuàng )建限定了作用域的變量。不過(guò),由 varStatus 屬性命名的變量并不存儲當前索引值或當前元素,而是賦予 javax.servlet.jsp.jstl.core.LoopTagStatus 類(lèi)的實(shí)例。該類(lèi)定義了一組特性,它們描述了迭代的當前狀態(tài),表 2 中列出了這些特性。
| 特性 | Getter | 描述 |
| current | getCurrent() | 當前這次迭代的(集合中的)項 |
| index | getIndex() | 當前這次迭代從 0 開(kāi)始的迭代索引 |
| count | getCount() | 當前這次迭代從 1 開(kāi)始的迭代計數 |
| first | isFirst() | 用來(lái)表明當前這輪迭代是否為第一次迭代的標志 |
| last | isLast() | 用來(lái)表明當前這輪迭代是否為最后一次迭代的標志 |
| begin | getBegin() | begin 屬性值 |
| end | getEnd() | end 屬性值 |
| step | getStep() | step 屬性值 |
清單 5 顯示了關(guān)于如何使用 varStatus 屬性的一個(gè)示例。這個(gè)示例修改了清單 4 中的代碼,將 Weblog 項的編號添加到顯示 Weblog 標題(title)的表行。它是通過(guò)為 varStatus 屬性指定一個(gè)值,然后訪(fǎng)問(wèn)所生成的限定了作用域的變量的 count 特性來(lái)實(shí)現這一點(diǎn)的。結果顯示在圖 5 中。
|

除 <c:forEach> 以外, core 庫還提供了另一個(gè)迭代標記: <c:forTokens> 。JSTL 的這個(gè)定制操作與 Java 語(yǔ)言的 StringTokenizer 類(lèi)的作用相似。清單 6 中顯示的 <c:forTokens> 標記除了比 <c:forEach> 的面向集合版本多一個(gè)屬性之外,其它屬性都相同。對于 <c:forTokens> 而言,通過(guò) items 屬性指定要標記化的字符串,而通過(guò) delims 屬性提供用于生成標記的一組定界符。和 <c:forEach> 的情形一樣,可以使用 begin 、 end 和 step 屬性將要處理的標記限定為那些與相應索引值相匹配的標記。
|
對于包含動(dòng)態(tài)內容的 Web 頁(yè)面,您可能希望不同類(lèi)別的用戶(hù)看到不同形式的內容。例如,在我們的 Weblog 中,訪(fǎng)問(wèn)者應該能夠閱讀各項,也許還應該能夠提交反饋,但只有經(jīng)過(guò)授權的用戶(hù)才能公布新項,或編輯已有內容。
在同一個(gè) JSP 頁(yè)面內實(shí)現這樣的功能,然后使用條件邏輯來(lái)根據每條請求控制所顯示的內容,這樣做常常能夠改善實(shí)用性和軟件維護。 core 庫提供了兩個(gè)不同的條件化標記 ― <c:if> 和 <c:choose> ― 來(lái)實(shí)現這些功能。
<c:if> 是這兩個(gè)操作中較簡(jiǎn)單的一個(gè),它簡(jiǎn)單地對單個(gè)測試表達式進(jìn)行求值,接下來(lái),僅當對表達式求出的值為 true 時(shí),它才處理標記的主體內容。如果求出的值不為 true ,就忽略該標記的主體內容。如清單 7 所示, <c:if> 可以通過(guò)其 var 和 scope 屬性(它們所起的作用和在 <c:set> 中所起的作用一樣)選擇將測試結果賦給限定了作用域的變量。當測試代價(jià)非常高昂時(shí),這種能力尤為有用:可以將結果高速緩存在限定了作用域的變量中,然后在隨后對 <c:if> 或其它 JSTL 標記的調用中檢索該結果。
|
清單 8 顯示了與 <c:forEach> 標記的 LoopTagStatus 對象的 first 特性一起使用的 <c:if> 。如圖 6 中所示,在這種情況下,只在 Weblog 項的第一項上顯示這組項的創(chuàng )建日期,而不在任何其它項前面重復該日期。
|

如清單 8 所示, <c:if> 標記為條件化內容的一些簡(jiǎn)單情形提供了一種非常簡(jiǎn)潔的表示法。對于需要進(jìn)行互斥測試來(lái)確定應該顯示什么內容的情況下,JSTL core 庫還提供了 <c:choose> 操作。清單 9 中顯示了 <c:choose> 的語(yǔ)法。
|
每個(gè)要測試的條件都由相應的 <c:when> 標記來(lái)表示,至少要有一個(gè) <c:when> 標記。只會(huì )處理第一個(gè)其 test 值為 true 的 <c:when> 標記體內的內容。如果沒(méi)有一個(gè) <c:when> 測試返回 true ,那么會(huì )處理 <c:otherwise> 標記的主體內容。注:盡管如此, <c:otherwise> 標記卻是可選的; <c:choose> 標記至多可有一個(gè)嵌套的 <c:otherwise> 標記。如果所有 <c:when> 測試都為 false ,而且又沒(méi)有給出 <c:otherwise> 操作,那么不會(huì )處理任何 <c:choose> 標記的主體內容。
清單 10 顯示了運用 <c:choose> 標記的示例。在這里,檢索請求對象而獲得協(xié)議信息(通過(guò) EL 的 pageContext 隱式對象),并用簡(jiǎn)單的字符串比較對協(xié)議信息進(jìn)行測試。根據這些測試的結果,會(huì )顯示相應的文本消息。
|
最后一個(gè)流控制標記是 <c:catch> ,它允許在 JSP 頁(yè)面內進(jìn)行初級的異常處理。更確切地說(shuō),在該標記的主體內容中產(chǎn)生的任何異常都會(huì )被捕獲并被忽略(即,不會(huì )調用標準的 JSP 錯誤處理機制)。然而,如果產(chǎn)生了一個(gè)異常并且已經(jīng)指定了 <c:catch> 標記的可選屬性 var ,那么會(huì )將異常賦給(具有頁(yè)面作用域的)指定的變量,這使得能夠在頁(yè)面自身內部進(jìn)行定制錯誤處理。清單 11 顯示了 <c:catch> 的語(yǔ)法(稍后在 清單 18中給出一個(gè)示例)。
|
![]() ![]() |
![]()
|
JSTL core 庫中的其余標記主要是關(guān)于 URL。這些標記中的第一個(gè)被適當地命名為 <c:url> 標記,用于生成 URL。尤其是, <c:url> 提供了三個(gè)功能元素,它們在為 J2EE Web 應用程序構造 URL 時(shí)特別有用:
清單 12 顯示了 <c:url> 標記的語(yǔ)法。 value 屬性用來(lái)指定基本 URL,然后在必要時(shí)標記對其進(jìn)行轉換。如果這個(gè)基本 URL 以一個(gè)斜杠開(kāi)始,那么會(huì )在它前面加上 servlet 的上下文名稱(chēng)??梢允褂?context 屬性提供顯式的上下文名稱(chēng)。如果省略該屬性,那么就使用當前 servlet 上下文的名稱(chēng)。這一點(diǎn)特別有用,因為 servlet 上下文名稱(chēng)是在部署期間而不是開(kāi)發(fā)期間決定的。(如果這個(gè)基本 URL 不是以斜杠開(kāi)始的,那么就認為它是一個(gè)相對 URL,這時(shí)就不必添加上下文名稱(chēng)。)
|
URL 重寫(xiě)是由 <c:url> 操作自動(dòng)執行的。如果 JSP 容器檢測到一個(gè)存儲用戶(hù)當前會(huì )話(huà)標識的 cookie,那么就不必進(jìn)行重寫(xiě)。但是,如果不存在這樣的 cookie,那么 <c:url> 生成的所有 URL 都會(huì )被重寫(xiě)以編碼會(huì )話(huà)標識。注:如果在隨后的請求中存在適當的 cookie,那么 <c:url> 將停止重寫(xiě) URL 以包含該標識。
如果為 var 屬性提供了一個(gè)值(還可以同時(shí)為 scope 屬性提供一個(gè)相應的值,這是可選的),那么將生成的 URL 賦值給這個(gè)限定了作用域的指定變量。否則,將使用當前的 JspWriter 輸出生成的 URL。這種直接輸出其結果的能力允許 <c:url> 標記作為值出現,例如,作為 HTML <a> 標記的 href 屬性的值,如清單 13 中所示。
|
最后,如果通過(guò)嵌套 <c:param> 標記指定了任何請求參數,那么將會(huì )使用 HTTP GET 請求的標準表示法將它們的名稱(chēng)和值添加到生成的 URL 后面。此外,還進(jìn)行 URL 編碼:為了生成有效的 URL,將對這些參數的名稱(chēng)或值中出現的任何字符適當地進(jìn)行轉換。清單 14 演示了 <c:url> 的這種行為。
|
清單 14 中的 JSP 代碼被部署到一個(gè)名為 blog 的 servlet 上下文,限定了作用域的變量 searchTerm 的值被設置為 "core library" 。如果檢測到了會(huì )話(huà) cookie,那么清單 14 生成的 URL 將類(lèi)似于清單 15 中的 URL。注:在前面添加上下文名稱(chēng),而在后面附加請求參數。此外, keyword 參數值中的空格和 month 參數值中的斜杠都被按照 HTTP GET 參數的需要進(jìn)行了編碼(確切地說(shuō),空格被轉換成了 + ,而斜杠被轉換成了 %2F 序列)。
|
當沒(méi)有會(huì )話(huà) cookie 時(shí),生成的結果如清單 16 中所示。同樣,servlet 上下文被添加到了前面,而 URL 編碼的請求參數被附加到了后面。不過(guò),除此以外還重寫(xiě)了基本 URL 以包含指定的會(huì )話(huà)標識。當瀏覽器發(fā)送用這種方式重寫(xiě)的 URL 請求時(shí),JSP 容器自動(dòng)抽取會(huì )話(huà)標識,并將請求與相應的會(huì )話(huà)進(jìn)行關(guān)聯(lián)。這樣,需要會(huì )話(huà)管理的 J2EE 應用程序就無(wú)需依賴(lài)由應用程序用戶(hù)啟用的 cookie 了。
|
![]() ![]() |
![]()
|
JSP 有兩種內置機制可以將來(lái)自不同 URL 的內容合并到一個(gè) JSP 頁(yè)面: include 偽指令和 <jsp:include> 操作。不過(guò),不管是哪種機制,要包含的內容都必須屬于與頁(yè)面本身相同的 Web 應用程序(或 servlet 上下文)。兩個(gè)標記之間的主要區別在于: include 偽指令在頁(yè)面編譯期間合并被包含的內容,而 <jsp:include> 操作卻在請求處理 JSP 頁(yè)面時(shí)進(jìn)行。
從本質(zhì)上講, core 庫的 <c:import> 操作是更通用、功能更強大的 <jsp:include> 版本(好像是 <jsp:include> “服用了興奮劑”的)。和 <jsp:include> 一樣, <c:import> 也是一種請求時(shí)操作,它的基本任務(wù)就是將其它一些 Web 資源的內容插入 JSP 頁(yè)面中。如清單 17 中所示,它的語(yǔ)法非常類(lèi)似于 <c:url> 的語(yǔ)法。
|
通過(guò) url 屬性指定將要導入內容的 URL,這個(gè)屬性是 <c:import> 的唯一一個(gè)必選屬性。這里允許使用相對 URL,并且根據當前頁(yè)面的 URL 來(lái)解析這個(gè)相對 URL。但是,如果 url 屬性的值以斜杠開(kāi)始,那么它就被解釋成本地 JSP 容器內的絕對 URL。如果沒(méi)有為 context 屬性指定值,那么就認為這樣的絕對 URL 引用當前 servlet 上下文內的資源。如果通過(guò) context 屬性顯式地指定了上下文,那么就根據指定的 servlet 上下文解析絕對(本地)URL。
但 <c:import> 操作并不僅僅限于訪(fǎng)問(wèn)本地內容。也可以將包含協(xié)議和主機名的完整 URI 指定為 url 屬性的值。實(shí)際上,協(xié)議甚至不僅局限于 HTTP。 <c:import> 的 url 屬性值可以使用 java.net.URL 類(lèi)所支持的任何協(xié)議。清單 18 中顯示了這種能力。
其中, <c:import> 操作用來(lái)包含通過(guò) FTP 協(xié)議訪(fǎng)問(wèn)的文檔內容。此外,還使用了 <c:catch> 操作,以便在本地處理 FTP 文件傳送期間可能發(fā)生的任何錯誤。錯誤處理是這樣實(shí)現的:使用 <c:catch> 的 var 屬性為異常指定一個(gè)限定了作用域的變量,然后使用 <c:if> 檢查其值。如果產(chǎn)生了異常,那么就會(huì )對那個(gè)限定了作用域的變量進(jìn)行賦值:如清單 18 中的 EL 表達式所顯示的那樣,該變量的值將 不會(huì )為空。由于 FTP 文檔的檢索將會(huì )失敗,因此會(huì )顯示有關(guān)這種情況的錯誤消息。
|
<c:import> 操作的最后兩個(gè)(可選的)屬性是 var 和 scope 。 var 屬性會(huì )導致從指定 URL 獲取的內容(作為 String 值)被存儲在一個(gè)限定了作用域的變量中,而不是包含在當前 JSP 頁(yè)面中。 scope 屬性控制該變量的作用域,缺省情況下是頁(yè)面作用域。如同我們在今后的文章中將要看到的那樣,JSTL xml 庫中的標記利用了 <c:import> 這種能力,即將整個(gè)文檔存儲在一個(gè)限定了作用域的變量中。
還要注意的是,可以使用(可選的)嵌套的 <c:param> 標記來(lái)為正在導入的 URL 指定請求參數。與在 <c:url> 中嵌套 <c:param> 標記一樣,必要時(shí)也要對參數名稱(chēng)和參數值進(jìn)行 URL 編碼。
![]() ![]() |
![]()
|
最后一個(gè) core 庫標記是 <c:redirect> 。該操作用于向用戶(hù)的瀏覽器發(fā)送 HTTP 重定向響應,它是 JSTL 中與 javax.servlet.http.HttpServletResponse 的 sendRedirect() 方法功能相當的標記。清單 19 中顯示了該標記的 url 和 context 屬性,它們的行為分別等同于 <c:import> 的 url 和 context 屬性的行為,是嵌套任何 <c:param> 標記的結果。
|
清單 20 顯示了 <c:redirect> 操作,它用一個(gè)到指定錯誤頁(yè)面的重定向代替了清單 18 中的錯誤消息。在該示例中, <c:redirect> 標記的用法與標準 <jsp:forward> 操作的用法類(lèi)似。不過(guò)請回憶一下:通過(guò)請求分派器進(jìn)行轉發(fā)是在服務(wù)器端實(shí)現的,而重定向卻是由瀏覽器來(lái)執行的。從開(kāi)發(fā)人員的角度來(lái)講,轉發(fā)比重定向更有效率,但 <c:redirect> 操作卻更靈活一些,因為 <jsp:forward> 只能分派到當前 servlet 上下文內的其它 JSP 頁(yè)面。
|
從用戶(hù)的角度來(lái)看,主要區別在于重定向會(huì )更新瀏覽器所顯示的 URL,并因此影響書(shū)簽的設置。轉發(fā)卻不這樣,它對最終用戶(hù)是透明的。這樣,選擇 <c:redirect> 還是 <jsp:forward> 還取決于所期望的用戶(hù)體驗。
![]() ![]() |
![]()
|
JSTL core 庫含有多種通用的定制標記,廣大的 JSP 開(kāi)發(fā)人員都會(huì )使用這些標記。例如,URL 和異常處理標記很好地補充了現有的 JSP 功能,如 <jsp:include> 和 <jsp:forward> 操作、 include 偽指令以及 page 偽指令的 errorpage 屬性。迭代和條件操作使得無(wú)需腳本編制元素就能夠實(shí)現復雜的表示邏輯,尤其在將變量標記( <c:set> 和 <c:remove> )與 EL 相結合使用時(shí)更是如此。
![]() ![]() |
![]()
|
core 庫中的幾個(gè)標記。 ![]() ![]() |
![]()
|
![]() | ||
![]() | Mark Kolb 是一位在德克薩斯州奧斯汀市(Austin)工作的軟件工程師。他常就服務(wù)器端 Java 這一主題在業(yè)界演講,而且還是 Web Development with JavaServer Pages, 第二版 一書(shū)的合著(zhù)者??梢酝ㄟ^(guò) mak@taglib.com與 Mark 聯(lián)系。 | |
聯(lián)系客服