1. 程式人生 > >jsf標籤,jsp標籤與jstl標籤

jsf標籤,jsp標籤與jstl標籤

JSF通過定製標籤與JSP整合。之前展示過的所有JSF標籤,<h:inputText>、<h:outputText>、<h:form>和<f:view>等,都是定製標籤。根據規範要求,JSF 實現必須通過提供訪問所有標準組件、呈現器、驗證器和轉換器的定製標籤來支援JSP。這些標籤庫(包括在JSF JAR中)列於表3-6中。

表3-6  JSF定製標籤庫

URI

名   稱

通用字首

說    明

http://java.sun.com/jsf/core

Core

f

包含獨立於特定呈現器的標籤(如<f:view>、<validator>,等等)

http://java.sun.com/jsf/html

HTML

h

包含所有標準組件和HTML呈現包

這些庫中的所有標籤都以某種特定的方式命名和實現。這樣,基於JSP的應用就保證可以在不同的 JSF 實現之間移植。大多數IDE,包括在本書中提到的,都可用於JSP開發。

因為JSP是唯一的所有實現都要求的顯示技術,我們在本書中都是用它來作為示例。如果你不使用JSP也沒關係,我們講述的大多數概念並未和某種顯示技術緊密相關,你可以在附錄A讀到有關使用其他顯示技術的資訊。

對大多數問題,在JSP中使用JSF僅是使用JSF定製標籤庫的問題。但是,也還有一些你需要知道的要點,比如JSP包含。

3.2.1  使用JSP包含

JSP的關鍵特徵之一是,能夠將來自於多個JSP頁面中的內容整合到一個頁面中。這通常用於完成包含頁首和頁尾之類的工作。JSP 支援兩類包含:動態的和靜態的。動態包含(通過<jsp:include>標籤或JSTL <c:import>標籤實現)在執行時訪問資源。這種情況下,控制被轉發到所包含的JSP。從被包含的JSP返回的響應將與呼叫頁面發回的響應進行合併。修改了動態的被包含頁面後,它們將在所有呼叫頁面中自動更新。

靜態包含在JSP轉換——即在頁面被轉換成Java 程式碼並且被編譯時,整合資源。原頁面的內容基本上是被拷貝到呼叫頁面中。對被包含頁面的修改不能在呼叫頁面時自動更新。因為它們已經有了自己的內容拷貝。它們必須是能夠被編輯的,以便它們在更新內容時被重新編譯(JSP 2.0的隱含包含,可以在web.xml中進行配置,其處理也類似於靜態包含)。

JSF支援兩種包含。對動態包含,有兩個要求:

l    被包含頁面必須封裝在JSF <f:subview> 核心標籤中。這個標籤可以位於被包含頁面中,也可以圍繞包含語句;

l    被包含頁面中的所有模板文字和非JSF標籤必須位於JSF <f:verbatim> 核心標籤之內。

所以,假定有下面的JSP頁面的程式碼片斷:

而Foo.jsp可能是這樣:

可以看到,整個被包含頁面被封裝在<f:subview>標籤中,並且所有的非JSF 標籤和模板文字封裝在<f:verbatim> 標籤中。另外,也可以將<f:subview> 標籤移到第一個頁面,圍繞在<jsp:include> 標籤之外。

使用靜態包含要更簡單些。無特別的限制——甚至並不非要使用<f:subview> 標籤。

在上例中,我們展示了一個假定的定製標籤,<customtag:dothis>,它可能執行任何任務。這樣就強調一個重點:可以和其他JSP定製標籤一起使用 JSF。

3.2.2  與JSTL以及其他JSP定製標籤一起使用JSF

這些有關JSF定製標籤庫的討論都很不錯,但是如果你希望有自己的定製標籤,或者使用第三方的標籤又如何呢?而如果你正在使用JSP 標準標籤庫(JSTL),這是能夠優雅地完成剛剛所述的所有事情的一套標準標籤,又該如何?多數情況下,可以將它們與你的JSF標籤混合使用。Faces標籤可以巢狀在其他標籤中。而對於某些產品,如IBM的WebSphere Application Developer [IBM,WSAD],鼓勵使用這種方法,而其他產品,如Sun的 Java Creator Studio [Sun,Creator],則鼓勵使用純粹的JSF方法。Oracle的 JDeveloper [Oracle,JDeveloper],允許你混合使用,但是也鼓勵你使用純粹的JSF方式。

註解    無論何時將JSF標籤巢狀到非JSF標籤中,一定要為它指定一個元件識別符號(見前一章關於元件識別符號的更多資訊)。

因為JSTL是標準,而且很多人對它都很熟悉,我們將用它來演示與定製標籤一起使用JSF(如果要獲得JSTL的詳細資訊,參考Shawn Bayern的一本非常棒的書JSTL in Action [Bayern])。從一個簡單的例子開始(如程式碼清單3-2所示)。該示例混合使用了一些JSTL 標籤和JSF 標籤。這段程式碼同時匯入了JSF 標籤庫和核心JSTL 標籤庫。

程式碼清單3-2  混合JSTL標籤和JSF標籤

在這個例子中,JSTL 和JSF 標籤都巢狀在JSF <f:view> 標籤中,而該標籤定義了JSF元件樹的開始。例子使用了JSF HtmlOutputText 元件(<h:outputText>)和JSTL <c:out> 標籤來顯示文字。JSTL <c:import> 標籤將系統的web.xml檔案包含到頁面中(實際上你一般是不可能想要與他人分享這個檔案的,因此不要在實際應用中這樣做)。因為web.xml 是一個XML 檔案,<c:import> 標籤被巢狀在<f:verbatim>標籤中,後者是JSF UIOutput 元件,其呈現器轉義了XML以便它在HTML頁面中正常顯示。這個例子並沒做什麼大不了的事情,但是它演示了在同一個頁面中混合使用不同標籤的能力。

注意,我們嵌套了JSTL標籤到JSF <f:verbatim> 標籤中。通常,巢狀JSF標籤到其他標籤之中是很容易的。事實上,任何可以顯示其子元件的元件,比如HtmlDataTable 和 HtmlPanelGrid,都要求模板文字和被巢狀的標籤位於<f:verbatim>標籤中(<f:verbatim> 標籤在第4章討論)。

隨同JSF使用JSTL最大的好處在於,兩者使用相似的表示式語言來引用物件(這對於JSP 2.0的表示式語言也是如此)。這樣使你可以很容易地以一種直觀的方式在JSTL和JSF標籤之間共享資料。為了演示這個特點,我們來看另一個例子,可以使使用者在HtmlInputText 控制元件中輸入數值,然後使用該數值通過JSTL <c:forEach> 標籤來重複顯示字串。程式碼示於程式碼清單3-3中。

程式碼清單3-3  對同一個後臺bean混合使用JSF 和JSTL 標籤

警告    如果和受管bean一起使用JSP或者 JSTL表示式,你需要確保被引用的bean已被建立,可以通過JSF表示式、Java程式碼或者你自己的定製標籤來實現。這是因為這些老的表示式語言並不知道JSF的受管bean建立工具(參考3.3節關於建立受管bean的資訊)。

這段程式碼引用了一個稱為exampleBean的JavaBean,它有個int型別的number 屬性。使用了HtmlInputText元件來基於使用者輸入更新bean的屬性值。使用者點選Go!按鈕(HtmlCommandButton元件)時,number屬性被更新,且頁面被重新顯示。這樣,JSTL <c:forEach>標籤將使用<c:out>標籤重複顯示文字exampleBean.number 次。<c:forEach> 標籤僅在exampleBean.number大於0時執行;這是由JSTL <c:if> 標籤控制的。

你不能在一個迭代其自身body的標籤中使用JSF元件標籤,如JSTL <c:forEach>標籤之中使用JSF標籤。推薦方法是使用HtmlDataTable 元件或者其他元件來在資料集或者集合之上進行迭代。

這個例子中,並沒有JSF 元件巢狀在JSTL <c:if>標籤中。但是如果元件被顯示一次後,然後在頁面重新顯示時又被諸如<c:if>之類的條件標籤隱藏,會怎樣?在元件第一次被顯示時,它被新增到檢視中。第二次,如果<c:if>標籤沒有顯示這個元件,JSF將把它從檢視中刪除。這意味著某些輸入控制元件將丟失其本地值,而你就不能再引用這些元件(通過客戶端識別符號引用或者在程式碼中引用)。我們來看另一個例子,如程式碼清單3-4所示,它來自於程式碼清單3-3的同一個頁面。

JSTL <c:if> 標籤在exampleBean.number 大於10時,將執行其body部分。如果body部分被執行,那麼所有巢狀的元件將被新增到檢視中,並顯示出來。反之,這些元件將被刪除(如果它們先前已被添加了)。這種情況如圖3-4所示。而圖3-5顯示的是程式碼清單3-3和3-4所用的頁面的輸出。

圖3-4    假設你通過JSTL條件標籤(或者其他定製標籤)來控制組件的可視性,如果某個元件未被顯示,它將被從檢視中刪除。這意味著元件也會忘記其本地值

程式碼清單3-4  通過JSTL有條件地顯示JSF元件

你也可以將這些元件放在HtmlPanelGroup中並且設定其rendered 屬性等於同一個表示式,以達到與程式碼清單3-4相同的效果。HtmlPanelGroup被用作多個元件的容器。如下例:

圖3-5    顯示於程式碼清單3-3和3-4中的JSP頁面的輸出。頂部的輸入欄位(HtmlInputText元件)的值被關聯到exampleBean.number後臺bean屬性,而該值被JSTL <c:forEach> 標籤用於重複顯示字串exampleBean.number次。在頁面的底部,如果exampleBean.number大於10,JSTL <c:if>標籤將使用JSF 元件顯示一個表單。否則,元件將不會被顯示,並且會被從檢視中刪除(並且輸入控制元件也將丟失其值)

如果exampleBean.number大於10,面板變為可見。這時,如果元件沒被顯示也將不被刪除。這是個不使用JSTL而使用純粹的JSF的好例子。

提示    即使定製標籤,像JSTL提供的那些,可以提供很多功能,但如果你正在從頭開發(或者重構),應該首先看看是否可以使用標準JSF元件來實現所需要的功能。使用優秀的元件和良好設計的後臺bean,可以避免在頁面中使用太多的JSTL 標籤。你可以使用JSF標準組件來隱藏和顯示整個面板,或者完成各種強大的任務。

下面是幾個隨JSTL國際化和格式化標籤一起使用JSF標籤的互操作性約束:

l    不推薦使用<fmt:parseDate> 和 <fmt:parseNumber>標籤。應該使用帶有DateTime 或者 Number 轉換器的(都在第6章討論)HtmlInputText 元件(第5章討論);

l    不應該使用用來決定或者指定頁面的字符集編碼的<fmt:requestEncoding> 標籤。通常,JSF 將自動處理這些,而如果需要強制指定特殊的編碼,應該使用JSP 頁面指令:<%page contentType="[content-type];[charset]"%>;

l    也不應該使用<fmt:setLocale>標籤。因為它不支援JSF,這可能會導致JSTL標籤使用一個場所而JSF 元件使用另一個場所,這將是一場災難。相反,你應該使用JSF的國際化特徵(在第6章討論)。為了控制特定頁面的場所,使用UIViewRoot 元件的locale屬性,這將在第4章討論。JSF的國際化特徵支援JSF和JSTL。

結合使用JSF 和JSTL的功能將是十分強大的。你自己開發的或者從第三方獲得的定製標籤都應該能夠可以很好的與我們這些所述的JSF和JSTL標籤一起工作。通常,你應該儘可能的堅持使用JSF 標籤。