級別: 中級
Joe Sam Shirah, 負責人和開發人員, conceptGO
2008 年 5 月 06 日
如
今,客戶希望并且已經開始期望基于瀏覽器的應用程序提供桌面特性。RichFaces 是用于 Java™ Server
Faces(JSF)的一種新的用戶界面組件套件。除了其他優點外, RichFaces 還提供內置的 JavaScript 和 Ajax
功能,從而滿足客戶期望。Joe Sam Shirah 根據最近的現場項目經驗,將一些新的工具添加到您的工具箱中,包括通過 Facelet 使用
RichFaces 的常見設置,以及一些特定的組件示例。
最近,一家
客戶委托我們實現一個項目,我認為這個項目非常棒。他們沒有專職的開發人員,要求我們設計和開發他們的第一個生產應用程序,該應用程序包括一個服務器和一
個瀏覽器客戶機。該應用程序將在他們的局域網和 Internet
上運行,并且使用一個虛擬專用網(VPN)。對于我來說,經歷一個項目從設想到實現再到培訓的整個過程并不鮮見,但還是很少有機會自主地確定項目的幾乎每
個方面。這個項目的一個主要方面是,每個人都習慣于桌面應用程序。如果在瀏覽器用戶界面中包括類似的特性,他們也許不會特別注意到,但是如果沒有這些特
性,他們肯定會有很多抱怨。例如,項目初始階段的主頁面將為動態查詢收集選擇標準。有些輸入區需要客戶端操作,至少有一個輸入區需要 Ajax
功能。最后,我選擇了 RichFaces 組件套,該組件套構建在 Ajax4jsf(參見 參考資料)之上,并與之合并。
 |
選擇組件
本文的目的不是倡導某一個產品或組件套件,而是讓您有足夠的信息開始使用 RichFaces,并且有足夠的背景知識,以便在開發自己的 RIA 或富 Web 客戶機時能作出比較。我鼓勵您嘗試各種可能性,參考本文和其他文章,得出自己的結論。
一個很好的起點是 JSF AJAX Component Library Feature
Matrix(參見 參考資料)。請務必仔細閱讀該頁面底部的每條注解,因為這個模型很少更新,而這個專區經常發生變化。我自己的簡短列表很快就減少到只有 RichFaces、Woodstock 和 IceFaces(見 參考資料)。
|
|
除了 Rich Internet Application(RIA)功能和 Ajax 外,我還需要:
- 開源的 LGPL 或 Apache 形式的許可,如果可能的話
- 使用 JSF 和 Facelets
- 和 JSF Reference Implementation(RI)組件一起使用
- 靈活但是一致的感觀或主題
- 足夠大的組件集,以覆蓋大多數應用程序需求
- 易于使用,不會出現阻塞
- 動態創建能力,有可用的 API
- 活躍的開發和社區
到目前為止,RichFaces 已經能滿足這些標準,這些組件在創建高效的、功能完備的應用程序方面已經顯現出價值。您的標準依舊可能變化。
本文探索一些有用的 RichFaces 特性,并提供一個用于演示的應用程序代碼(參見 下載 小節)。不過,在討論 RichFaces 之前,需要介紹一些必要的基礎設施元素。
從頭開始
雖然在初始階段客戶的應用程序可以只使用一個
servlet 容器,但是將來會需要更多的支持,并且很可能要包括用于其他子公司的項目。為了盡量靠近標準,我選擇開源的 Glassfish Application Server V2,它支持
JEE 5,并且使用 Java SE 6 作為底層運行時。至于 Web 框架,我選擇 JSF
和 Facelets。一個額外的好處是,Java EE 5 中包括了 JSF 支持;對于
Glassfish V2、WebSphere Application Server Community Edition V2 等等,受支持的
JSF 版本是 1.2。JSF 2.0 的目標是獲得 Facelets(或類似的)支持,最主要的 Facelets 開發人員都屬于 JSF 專家組。
本文假設讀者有這些方面的基礎知識。示例代碼下載小節包括了您需要的用于 Tomcat 6.0.16 和 Glassfish 的所有文件,并且這些文件都在這兩者上經過測試。在線版本(參見
參考資料)在 Glassfish V2 上運行。如果您需要關于這些技術的更多背景知識,請參閱 參考資料,并訪問適當的鏈接。
并不是更小的 JSF 版本
Facelets 并不像其名稱那樣表示一個小號的 JSF;相反,在其核心,Facelets 提供了 JSP 的替代品 JSF
ViewHandler
,而這正是我在本文要使用的內容。當我第一次研究 JSF 時,我曾閱讀過 Hans Bergsten 的文章 “Improving JSF
by Dumping JSP”(參見 參考資料)。之后不久,我就發現了 Facelets,此后就一味沉浸于此。Facelets 支持所有的 JSF
UI 組件,并且構建了它自己的組件樹,以反映 JSF 應用程序的視圖。雖然 JSP 和 JSF 技術已得到改進,如今可以更好地協作,但是 Facelets 完全消除了 Bergsten 的文章中提到的問題。
我喜歡讓事情盡量簡單而直接。在示例項目中您將看到,實際上所有代碼(而不是標記)都是由用于 getter、setter 和方法綁定的
Expression Language(EL)表達式組成的。雖然更復雜的項目可能需要更復雜的表達式,但是通常情況下 Facelets 便于將
Java 代碼與 Web 頁面標記分隔開。
在這里您將注意到,這種開發與使用 JSP 的 “常規” JSF 開發的主要不同之處在于:
- 您將需要 jsf-facelets.jar。
- web.xml 和 faces-config.xml 中的一些標注。
- Web 頁面是 XHTML 文檔。
- 使用 XML 名稱空間,而不是 JSP 標記庫。
隨著格式化的進行,不僅僅是初始部分(參見
清單 1),Web
頁面中的所有部分看上去都應該很熟悉。我將這個特性視為 Facelets 的一個樸素特性。對于本文的項目,以及將 Facelets
主要用于視圖的其他項目,您實際上只需要知道這一點。Facelets 還包括很多其他有用的特性,例如為方便 Web
頁面設計者而提供的簡單的模板和元素。如果讀者有興趣了解更多關于 Facelets 的信息,建議從 “Inside Facelets Part
1: An Introduction”(參見 參考資料)入手。
清單 1. Facelets XHTML 文檔的初始部分
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" >
|
演示組件
RichFaces 看上去非常強大;平均每個組件有超過 20
個特定的屬性,并且還有非常多的通用屬性。但是,大多數屬性都有合理的默認值,在一般使用過程中,這些組件的設置并不困難。有些花哨的組件可以處理各種不
同的效果,例如 Google Maps 和 Virtual
Earth。您可能想使用它們來讓用戶感到興奮,但是在這里我還是著重關注那些在很多應用程序中都有用的組件。這足以讓我興奮。
本文主要演示的組件有:
我們還將使用一個 Panel Bar 進行說明。圖 5 顯示了一個示例:
圖 5. RichFaces Panel Bar
組件
我們將使用 Simple Toggle Panels 顯示結果。圖 6
顯示了一個示例:
圖 6. RichFaces Simple Toggle
Panel 組件
如前所述,RichFaces 構建在 Ajax4jsf 之上。以此為基礎,任何組件都可以以幾種不同的方式支持 Ajax。本文中的示例應用程序為 Suggestion Box 和 Simple
Toggle Panel 組件使用 Ajax 功能。
華麗的界面
dWRFDemo1
示例應用程序很小。它的真正目的是演示所選擇組件的設置和使用。因此,它只是收集和顯示輸入數據。至于如何在生產應用程序中使用數據和組件,我留給您自己
去想象。除了必要的 JAR、圖像、用作資源包的屬性文件以及級聯樣式表(Cascading Style
Sheets,CSS)文件外,該應用程序包括兩個 XHTML 頁面和兩個 Java 類。這種簡潔性允許代碼具有 IDE
不可知性。實際上,我故意使用一個 Java 編輯器、文件的 Wordpad、javac
和 jar
命令進行創建。
圖 7 顯示了輸入頁面的 URL,這里假設 Tomcat 或 Glassfish 采用默認設置,這個 URL 為
http://localhost:8080/dWRichFacesDemo1。
這個輸入頁面允許使用 Calendar 組件選擇一個日期。Order
By List Shuttle 組件讓您可以移動和重新排列可用項目。
City Suggestion Box 讓您可以輸入一個城市名稱。City 啟用了 Ajax 支持;
如果按下空格鍵,將顯示所有可用的城市。如果鍵入首字母為 A 或 J 的城市名稱,那么將列出相應的城市。隨著輸入的字符數逐漸增多,列表中可用的城市范圍逐漸縮小??梢詥螕糇髠鹊?Panel Bar 條目,查看基本的組件說明。
圖 7.
dWRFDemo1
輸入頁面
輸入完畢后,單擊 Submit 按鈕。
這個應用程序很小,不會執行任何編輯。由于 Calendar 組件禁止手動輸入,所以不可能輸入無效的日期。
通過 Submit 按鈕可以顯示結果頁面,如
圖 8 所示:
圖 8.
dWRFDemo1
結果頁面
在結果頁面上,單擊 Result 選項卡,然后單擊適當的 Simple
Toggle Panel 條目,以查看輸入值。單擊 Edit 按鈕返回到輸入頁面。
設置
對于一個應用程序,最重要的東西是 JSF、Facelets 和
RichFaces 的實現者 — 即實現這些功能的 JAR。這些 JAR 被包括在可下載的 WAR 的 lib 目錄中(參見 下載 小節),下面的列表標出了它們的版本。該列表假設您的 Web 容器支持當前的 EL 和 servlet API 版本。如果在運行該演示應用程序時遇到問題,請檢查 JSF、Facelets 和 RichFaces 的需求(參見 參考資料)。您還應該查看
下載說明。
- JSF 1.2 (包括在 Glassfish V2 中)
- Facelets 1.1.14
- RichFaces
- richfaces-api-3.1.4.GA.jar
- richfaces-impl-3.1.4.GA.jar
- richfaces-ui-3.1.4.GA.jar
- 雖然沒有明確要求,但是 RichFaces 假定下面這些 JAR 也是可用的:
- commons-beanutils-1.7.0.jar
- commons-collections-3.2.jar
- commons-digester-1.8.jar
- commons-logging-1.0.4.jar
- jhighlight-1.0.jar
下面 清單 2 中顯示了用于啟用 JSF 的 web.xml 條目:
清單 2. web.xml 中需要的最少的 JSF 條目
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
|
清單 3 顯示了 Facelets 需要的另一個條目。該條目覆蓋了默認后綴 .jsp。通常,對于 faces-config.xml 中的視圖處理程序,Facelets 需要另一個覆蓋條目,但是正如您將從下面看到的那樣,RichFaces
將覆蓋包括在 web.xml 中。
清單 3. 用于 Facelets 后綴的 web.xml 條目
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
|
清單 4 顯示了 web.xml 中實現
RichFaces 所需的元素:
清單 4. 用于實現 RichFaces 的 web.xml 條目
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>classic</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
|
我將按照操作順序解釋清單 4 中的元素,而不是按照它們在 web.xml 中的出現順序。
-
<filter>
和
<filter-mapping>
RichFaces 使用一個過濾器來處理 Ajax 請求中接收到的代碼。這些元素定義過濾器類(org.ajax4jsf.Filter
),并將它映射到 清單 2 中定義的 JSF Faces
Servlet。
-
<context-param>
和
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
RichFaces 需要知道應用程序中將使用 Facelet。這些元素執行這個任務,并有效地替換 faces-config.xml 中常規的 Facelets
條目。注意,Facelets 視圖處理程序類是
com.sun.facelets.FaceletViewHandler
。
-
<context-param>
和
<param-name>org.richfaces.SKIN</param-name>
RichFaces 有一些內置的配色方案或皮膚。這些元素定義要在應用程序中使用的皮膚。
classic
皮膚是中等程度的藍色。
關于清單 2、3 和 4 中的條目,好的方面是,在所有應用程序中它們幾乎都是一樣的,實際上這就是樣板代碼。此外,還有一段代碼也是在每個應用程序中可以看到的:清單 5 是
清單 1 的修改版,用于將 RichFaces 名稱空間包括在應用程序的 XHTML 頁面中:
清單 5. Facelets/RichFaces XHTML 文檔的初始部分
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich" >
|
準備好了
現在,我們可以開始使用 RichFaces 組件。從 Panel Bar 和
Panel Bar Items(參見 圖 5)開始。您可能不經常使用這些組件,但是它們都很容易使用,并且為
RichFaces 語法提供了第一個良好的用例。
這里的思想是,Panel Bar 是 Panel Bar Items 的一個容器。每個 Panel
Bar Item 有一個標簽,并且可以包含任何其他組件。Panel Bar Items 位于另一個 Panel Bar Items 之上;當單擊條目欄時,將顯示實際的內容。每次只顯示一個條目的內容。在這個應用程序中,如 清單 6 所示,我們將使用文本。注意,所有組件都有一個 rich:
前綴,以引用 清單 5 中包括的名稱空間項。
清單 6. RichFaces Panel Bar 組件
<rich:panelBar height="192" width="256">
<rich:panelBarItem label="#{dWRFD1.calComp} #{dWRFD1.info}">
<h:outputText value="#{dWRFD1.calCompText}" style="font: menu;" />
</rich:panelBarItem>
<rich:panelBarItem label="#{dWRFD1.lsComp} #{dWRFD1.info}">
<h:outputText value="#{dWRFD1.lsCompText}" style="font: menu;" />
</rich:panelBarItem>
<rich:panelBarItem label="#{dWRFD1.sbComp} #{dWRFD1.info}">
<h:outputText value="#{dWRFD1.sbCompText}" style="font: menu;" />
</rich:panelBarItem>
</rich:panelBar>
|
 |
<f:loadBundle> 在哪里?
在 JSF 1.2 中,可以在 faces-config.xml 中定義基于屬性的資源包,所以不再需要在每個頁面上使用
<f:loadBundle> 。該定義類似于用于 managed bean 的條目,但是特定于資源包。例如:
<resource-bundle>
<base-name>dWRFDemo1</base-name>
<var>dWRFD1</var>
</resource-bundle>
|
|
|
基本的 <rich:panelBarItem />
元素只需要一個標簽,它是通過一個 EL 表達式從資源包中提取到這里的。
演示 Panel Bar Items 的實際內容只是一個
<h:outputText />
元素,它同樣也具有來自資源包的文本。為提高可讀性,我使用一個 font
樣式元素,同時這也表明了 RichFaces 支持 CSS 的靈活性。
注意,對于生成的 JavaScript,不需要程序員的任何參與。只需簡單幾步,就可以創建一個好看的、多面板的、可單擊的組件。這正是 RichFaces 的一個強大之處。即使是像這樣簡單的組件,也可以有 active/inactive 樣式、事件等。
確定日期
Calendar 組件(如 圖 1 所示)您應該比較熟悉;日期選擇也許是 JavaScript 對 Web 頁面最早的增強之一。RichFaces Calendar 有超過 80 個可用屬性,但是,正如 清單 7 所示,您通常只用到其中很少一部分:
清單 7. RichFaces Calendar 組件
<label for="CalendarID" >#{dWRFD1.calendar}:</label>
<rich:calendar name="Calendar" id="CalendarID"
value="#{dWRFD1Handler.selectedDate}"
timeZone="#{dWRFD1Handler.timeZone}"
datePattern="#{dWRFD1.datePattern}" >
</rich:calendar>
|
datePattern
屬性需要 java.text.SimpleDateFormat
定義的一個標準的日期模式。這個示例同樣使用資源包來提供值,它將
datePattern
定義為
yyyy-MM-dd
。value
和 timeZone
屬性是使用來自一個 managed bean 的方法裝載的,這個 bean 的定義如 清單 8 所示:
清單 8. 用于 dWRFD1Handler
的 managed bean 定義
<managed-bean>
<managed-bean-name>dWRFD1Handler</managed-bean-name>
<managed-bean-class>com.dW.dWRFD1Handler</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
|
com.dW.dWRFD1Handler
類很簡單,主要由一個初始化程序、getter 和 setter 組成,對它應該沒必要再作討論。getSelectedDate()
和
setSelectedDate()
方法需要一個
java.util.Date
。
getTimeZone()
方法只是返回
java.util.TimeZone.getDefault()
;在生產中,這樣做是否合適取決于應用程序的需求。
如果您還想允許用戶輸入日期值,那么可以將
enableManualInput
屬性設為
true
。如果您只想顯示 Calendar,那么將
popup
屬性設置為 false
。
顯然,還有很多其他屬性可以設置,但是對于基本的 Calendar 功能只需做這么多。
多種方法
List Shuttle 組件(參見 圖 2)是從一個初始組中選擇項目并對選定的項目排序的理想組件。
清單 9 表明,它比您想象的更容易使用:
清單 9. RichFaces List Shuttle 組件
<label for="OrderByID">#{dWRFD1.orderBy}:</label>
<rich:listShuttle sourceValue="#{dWRFD1Handler.orderBySource}"
name="OrderBy" id="OrderByID"
targetValue="#{dWRFD1Handler.orderByTarget}" var="items"
<h:column>
<h:outputText value="#{items}"></h:outputText>
</h:column>
</rich:listShuttle>
|
示例代碼中實際的 XHTML 標記包括更多屬性,以覆蓋某些默認的標簽,但是通常情況下只需
sourceValue
、targetValue
、
var
和 column
屬性。
sourceValue
和
targetValue
值是包含任何類型的對象的
java.util.List
類。和演示代碼一樣,大多數情況下您將使用包含
String
的列表。清單 10 并不是初始化 sourceValue
,而是顯示與示例 List Shuttle 相關的所有 Java 代碼。
清單 10. 相關的 dWRFD1Handler
List Shuttle 代碼
private List<String> lOrderBySource = new ArrayList<String>(),
lOrderByTarget = new ArrayList<String>();
...
public List getOrderBySource()
{
return lOrderBySource;
}
public List getOrderByTarget()
{
return lOrderByTarget;
}
...
public void setOrderBySource( List<String> orderBySource )
{
lOrderBySource = orderBySource;
}
public void setOrderByTarget( List<String> orderByTarget )
{
lOrderByTarget = orderByTarget;
}
|
var
屬性聲明一個變量,該變量將用于對列表進行迭代,JSF 組件經常使用這種模式。如果列表中的對象支持多個字段,那么實際上這里可以使用多個列。在這種情況下,
value="#{items}"
被改為
value="#{items.getterMethodName}"
,這應該沒什么好奇怪的。在這里,我們使用的是一個 String
類列表,因此只有一個列。用戶做出選擇之后,在提交時處理程序會收到排好序的目標列表,其中包含用戶的選擇。
Suggestion Box 組件
如果您經常使用論壇和郵件列表,那么您遲早會看到人們如何將數千乃至數百萬條目下載到一個下拉列表中。Suggestion Box 組件(參見 圖 3)
提供一種方式來顯示有效的選擇,使用戶不必面對那樣極端的情況。 實際上,這一點正是我開始研究 RichFaces
和類似套件的主要原因,因為應用程序中有些輸入項,例如城市,有太多的可選項,這種情況下下拉列表已經不適用了。Suggestion Box
的功能類似于我們熟悉的很多桌面應用程序中提供的自動完成組件。顯然,為了讓這種功能有機會在 Web 應用程序中有效地工作,必須借助 Ajax
提交。
清單 11 顯示了該功能所需的三種不同的組件:label 和 input text(注意,這些是標準的 JSF RI 組件)、
<a4j:region>
以及
<rich:suggestionbox>
。
<h:inputText>
使用
getCity()
和 setCity()
方法和 managed bean 來為它提供值。字段的輸入可以通過鍵盤,也可以通過從 Suggestion Box 中進行選擇。
清單 11. RichFaces Suggestion Box 組件
<label for="CityID">#{dWRFD1.city}:</label>
<h:inputText name="City" id="CityID" size="10"
value="#{dWRFD1Handler.city}" />
<a4j:region renderRegionOnly="true">
<rich:suggestionbox id="citySuggestionBoxId" for="CityID"
suggestionAction="#{dWRFD1City.suggest}" var="result"
eventsQueue="foo" ignoreDupResponses="true"
selectedClass="selCtl" >
<h:column>
<h:outputText value="#{result}" style="font: menu;" />
</h:column>
</rich:suggestionbox>
</a4j:region>
|
<a4j:region>
表示在 Ajax 提交時發送的一個區域。您需要清楚,通常情況下,如果沒有包括任何區域,RichFaces 會假定一個默認區域,這個區域的范圍是從
<f:view>
到
</f:view>
。這實際上就是整個頁面。當我第一次使用
<rich:suggestionbox>
時,本來一切都正常,但是在單步調試時卻發現,所有其他字段也會隨之一起提交,也會被驗證、轉換并經過 JSF 的整個生命周期。簡單地說,這對于需要對每次按鍵都作出響應的組件來說不是件好事。RichFaces Developer Guide(參見
參考資料)中有一段內容討論了通常情況下適用的另一種形式的 Ajax 提交,應該給出了正確的方法:
注
意,"ajaxSingle"="true" 可以減少將來的傳輸,但是不會阻止服務器端對其他輸入組件的解碼。有些 JSF 組件,例如
<h:selectOneMenu>,會重新識別請求映射值中作為 null
值丟失的數據,并嘗試通過驗證過程并得到失敗的結果。因此,必要時可以使用 <a4j:region>
來限制將在服務器端處理的組件樹的一部分。
至于 renderRegionOnly
屬性,RichFaces
Developer Guide 這樣描述:
禁止在活動區域以外的 AJAX 響應內容中呈現的標志。如果該屬性被設為 “true”,那么區域以外的組件不會包括在 AJAX 響應中。如果該屬性被設為 “false”,那么將會在整個樹中搜索要加入到響應中的組件。該屬性的默認值為 “false”。
在本例中,我們希望惟一回到服務器的元素是
suggestionAction
方法請求和它的
Object
參數(通過鍵盤當前輸入的
String
)。返回時,應該只更新和呈現 Suggestion Box 內容。
Suggestion Box 本身需要的最基本的屬性是
suggestionAction
、var
和至少一個用于顯示結果的列。
suggestionAction
方法是另一個 managed bean 中的
suggest()
,這個 bean 基于 demo 代碼中的第二個 Java 類 com.dW.City
。該方法的簽名為:public List suggest(Object anObject)
。
在 demo 代碼中,在初始化時首先創建一個以 A 和 J 開頭的城市的列表。如果用戶在 City
文本域中按下空格鍵,則返回完整的列表。如果按下 A 鍵,則返回一個包含以 A 開頭的城市的子列表。對于以 J
開頭的城市也是如此。每鍵入一個字符,結果就會隨之縮小。在您自己的代碼中,只要與輸入相符,你可以做任何事情。在實際應用程序中,結果來自一個有限的數
據庫集合,這也許是最常見的。如果您熟悉這種數據,那么也許可以修改一下這個方法,看能不能優化結果。例如,我曾經碰到一個示例,有些按鍵是可以忽略的,
所以該方法可以直接返回,而不必訪問數據庫了。
var
屬性定義一個迭代變量,以便在輸出列內容時使用。它與
List Shuttle 組件的 var
屬性的用法是一樣的。
eventsQueue
屬性不是必需的,但是我建議您也同樣對待。您只需添加該屬性,并提供一個名稱。它會執行兩個重要的服務:
- 將方法調用(事件)放入隊列,以保證順序。在隊列中,在前一個方法請求返回之前,不會發送下一個方法請求。
-
如果隊列中有多個同種類型的事件,那么只發送最新的那個。例如,Suggestion Box
對于每次按鍵都發送一個請求。如果當之前的請求返回時隊列中有多個按鍵請求,那么只將最新的按鍵請求發送到服務器。記住,雖然對于每次按鍵都會發送請求,
但是發送的參數是 input text 組件的整個內容。
ignoreDupResponses
屬性的作用應該是不言而喻的。
selectedClass
是應用于該組件的一個 CSS 類。RichFaces 使用皮膚(skin)的概念。這是通過組件上的選擇欄實現的。我自己的應用程序有幾個 RI 下拉列表在選擇欄中使用了系統顏色。Suggestion Box 使用
classic
皮膚顏色,這讓外觀看起來有些不一致。SelCtl
類告訴 Suggestion Box
使用系統的高亮顯示顏色。
存放標簽
Tab Panel 組件(參見 圖 4)很容易使用。通常的 RichFaces 屬性在該組件中都可以使用,但是您將使用的主要屬性是 switchType
。該屬性的默認值為
server
,但是您可能最常用的值反而是
client
。ajax
屬性也可以使用。如 清單 12 所示,這里使用一個典型的
RichFaces “三明治式” <rich:tabPanel>
元素和堆疊的 “三明治式” <rich:tab>
元素來創建一組選項卡式頁面:
清單 12. RichFaces Tab Panel 組件
<rich:tabPanel switchType="client" >
<rich:tab label="#{dWRFD1.info}">
#{dWRFD1.resultText}
</rich:tab>
<rich:tab label="#{dWRFD1.result}">
</rich:tab>
</rich:tabPanel>
|
label
屬性用于顯示選項卡的名稱。在 demo 代碼中,和通常一樣,label
的值是從資源包中提取的。和 Panel Bar Items 類似,選項卡可以包含任何類型的組件。對于 demo,我使用資源包文本作為 Info 選項卡的內容,使用 Simple Toggle Panels 作為 Result 選項卡的內容。
完成
我猜您可能在想:“這些都很簡單”。這就對了。一旦理解了 RichFaces 的基礎,大多數組件使用起來都很簡單。因此,對于 Simple Toggle Panel
(參見 圖 6 和 清單 13)我只講一點點,其他的就留給您作為練習吧。
清單 13. RichFaces Simple Toggle Panel 組件
<h:panelGrid columns="1" width="50%">
<rich:simpleTogglePanel switchType="ajax"
label="#{dWRFD1.calComp} #{dWRFD1.value}" opened="false" >
#{dWRFD1Handler.selectedDate}
</rich:simpleTogglePanel>
<rich:simpleTogglePanel switchType="ajax"
label="#{dWRFD1.lsComp} #{dWRFD1.value}" opened="false" >
#{dWRFD1Handler.orderByTarget}
</rich:simpleTogglePanel>
<rich:simpleTogglePanel switchType="ajax"
label="#{dWRFD1.sbComp} #{dWRFD1.value}" opened="false" >
#{dWRFD1Handler.city}
</rich:simpleTogglePanel>
<rich:simpleTogglePanel switchType="ajax"
label="#{dWRFD1.face}" opened="false" >
<img src="images/myphoto.jpg"
height="80" width="64"/>
</rich:simpleTogglePanel>
</h:panelGrid>
|
Simple Toggle Panel 由一個條狀欄和一個內容顯示組成,后者可以是任何組件。通過單擊條狀欄,可以顯示或隱藏內容,這非常像只有一個項目的 Panel Bar。注意,
switchType
屬性再次出現。
opened
屬性確定是否在第一次顯示時顯示內容。對于這個 demo,我將多個 Simple Toggle Panels 放在一個
JSF RI <h:panelGrid>
中,后者被放在一個 Tab 中,而這個 Tab 則被放在一個 Tab Panel 中。
結束語
RichFaces 為構建 RIA 和支持 Ajax 的 Web 應用程序提供了大量的 JSF
組件。本文只演示了其中一小部分,但是您應該已經大致了解 RichFaces
背后的原理,并且也看到了在很多應用程序中可能有用的組件。該組件套件中的所有組件都有在線的 demo、文檔和其他資源,這些資源可以從
RichFaces 主頁的 “Most Important Links” 區獲得(參見 參考資料)。
如果您選擇使用 RichFaces,那么我鼓勵您深入探索文檔中討論的
a4j:
組件和處理,以理解如何將這些概念應用到其他 RichFaces
組件上。有時候研究可能會延長開發時間,讓客戶覺得備受挫折,然而,另一方面,投入的研究時間在開發過程和運行時性能方面會得到很多回報。
包含更多組件的 RichFaces 3.2 有望在 2008 年三月底發布。無論您使用哪個 RIA 組件集,這種激烈的競爭應該有助于提高它們的穩定性和生產率。
下載
描述 | 名字 | 大小 | 下載方法 |
本文的 WAR 演示文件1 |
j-RichFacesDemo1.zip |
5.5MB |
HTTP |
注意:
- 由于源文件和 WAR 文件只差兩個文件 — Java 文件 — 我將 Java 源文件放在 WAR 文件中。因此,這里只有一個下載文件。要獲得關于使用 WAR 文件的說明,請參閱下載中包含的 readme.txt 文件。
參考資料
學習
獲得產品和技術
討論
關于作者
 |
|
 |
Joe Sam Shirah 是 conceptGO
的負責人和開發人員,該公司提供遠程咨詢和軟件開發服務以及產品,專長是 JDBC、I18N、AS/400、RPG、金融、庫存以及后勤方面。Joe
Sam 于 1998 年 JavaOne 上獲得 Java 社區獎,他也是 Java Developer Connection 上的 JDBC 2.0 Fundamentals 短期課程的作者。他是 developerWorks“Java filter”論壇的主持人,還是 jGuru 的 JDBC、國際化和 Java400 FAQ 的管理人員。Joe Sam 擁有經濟學工商管理學士學位以及國際管理碩士學位??梢酝ㄟ^ joesam@conceptgo.com 和 Joe Sam 聯系。
|