在這個(gè)分五部分的教程系列的前兩期中,研究了 JavaServer? Faces(JSF),這是一種新的基于 Java? 的框架,可以簡(jiǎn)化為 Java Platform, Enterprise Edition(Java EE)應用程序構建圖形用戶(hù)界面(GUI)的過(guò)程。我們構建并成功地在 Apache Geronimo 上部署了一個(gè)簡(jiǎn)單的 JSF 應用程序,并學(xué)習了如何將 Apache Tomahawk(它提供幾個(gè)與 JSF 100% 兼容的組件)與應用程序進(jìn)行集成以改進(jìn)界面。在本教程(第 3 部分)中,將了解 Sun Ajax4jsf 開(kāi)放源碼框架,這個(gè)框架為 JSF 應用程序添加 Asynchronous JavaScript? + XML(Ajax)功能,而無(wú)需編寫(xiě)任何 JavaScript 代碼。將使用 Ajax4jsf 改進(jìn)示例應用程序并創(chuàng )建一個(gè)啟用 Ajax 的前端。
開(kāi)始之前
本教程向 Java 程序員講解如何使用 JSF 組件構建高度交互性的部署在 Apache Geronimo 上的 Java EE 應用程序。本教程假設讀者將使用 Eclipse IDE 作為開(kāi)發(fā)平臺。
關(guān)于本教程
本教程講解 Sun Ajax4jsf 開(kāi)放源碼框架,這個(gè)框架為 JSF 應用程序添加 Ajax 功能,而無(wú)需編寫(xiě)任何 JavaScript 代碼。我們將繼續改進(jìn) 第 2 部分 開(kāi)發(fā)的示例應用程序,增加一個(gè)對溫度進(jìn)行轉換并以圖形化方式顯示結果的實(shí)用程序。
關(guān)于本系列
本教程是關(guān)于使用 JSF 構建 Apache Geronimo 應用程序的分五部分的教程系列的第 3 部分。整個(gè)系列教程包括以下幾個(gè)部分:
第 1 部分:使用 Eclipse 和 Apache MyFaces Core 構建基本的應用程序 介紹如何使用 JSF 標準的 Apache MyFaces 實(shí)現以及 Geronimo(一種也是來(lái)自 Apache 的免費應用服務(wù)器)。這個(gè)教程講解如何使用 Eclipse IDE 的 Web Tool Platform(WTP)來(lái)構建 JSF 應用程序。
第 2 部分:在 JavaServer Faces 中使用 Tomahawk 展示如何在 Geronimo 應用程序中集成 Apache Tomahawk。Tomahawk 提供了幾個(gè)與 JSF 100% 兼容的定制組件。
第 3 部分:在 JavaServer Faces 中使用 ajax4jsf 演示如何使用 Sun 的免費開(kāi)放源碼框架 ajax4jsf 在 Geronimo 應用程序中添加 Asynchronous JavaScript + XML(Ajax)功能。
第 4 部分:使用 Application Development Framework(ADF)Faces 擴展 JSF 講解怎樣將 ADF Faces 中的組件集成到 Geronimo 應用程序中。Oracle 的 ADF Faces 是構建于 JSF 之上的一組非常豐富的 UI 組件(它是用 Trinidad 這個(gè)名稱(chēng)捐獻給 Apache 的代碼的一部分)。
第 5 部分:將 JSF 應用程序與 Spring 集成 展示如何將 JSF 應用程序與 Spring 框架集成。Spring 是一個(gè)流行的框架,它使 Geronimo 開(kāi)發(fā)者能更容易地構建 Java EE 應用程序。
系統需求
為了學(xué)習本教程,需要有下列工具:
第 2 部分 源代碼,我們將對這個(gè)應用程序進(jìn)行改進(jìn)。
Geronimo,Apache 的 Java EE 服務(wù)器項目。根據需要,Geronimo 提供 Tomcat 和 Jetty 兩種風(fēng)格。我們采用的是 Jetty 風(fēng)格(1.1 版),因為它小一點(diǎn)兒。
MyFaces,Apache 的 JSF 實(shí)現。請從 Apache 下載核心版本(不帶 Tomcat)。本教程中使用的版本是 1.1.3 版。
Tomahawk,它提供用于 MyFaces 的額外組件和輸入驗證器,同時(shí)與 JSF 100% 兼容。
Eclipse,這是一個(gè)可支持大量語(yǔ)言和平臺的可擴展開(kāi)放源碼 IDE。
Eclipse Web Tools Platform(WTP),它給 Eclipse 添加了對 XML 和 JavaScript 編輯的支持以及對 JSF 的基本支持。
Ajax4jsf,這是 Sun 的開(kāi)放源碼框架,用于在現有的 JSF 應用程序中添加 Ajax 功能。在編寫(xiě)本文時(shí)的當前版本是 1.0rc4。
將 Java 1.4 或更新版本 安裝到您的系統中。Eclipse 二進(jìn)制文件中帶有自己的 Java 運行時(shí),但 Geronimo 和 MyFaces 則沒(méi)有(帶運行時(shí)會(huì )使下載歸檔文件的尺寸顯著(zhù)變大)。
Ajax4jsf —— 概述
Ajax4jsf 允許開(kāi)發(fā)人員將 Ajax 功能添加到 JSF 應用程序中,而不需要 JavaScript 或用 Ajax 圖形部件替換現有的組件。這個(gè)包還允許在使用 Java 2D 庫時(shí)動(dòng)態(tài)地生成圖像。Ajax 是一種編程技術(shù),它處理只有頁(yè)面的一部分需要處理而不需要重新裝載整個(gè)頁(yè)面的情況。這種方式的好處包括減少服務(wù)器上的處理時(shí)間以及加快客戶(hù)端的響應速度。
與 Tomahawk 相似,Ajax4jsf 提供了一套可以很容易地與 JSF 標記一起使用的標記。在本教程后面對 Developer Forum Signup 示例應用程序進(jìn)行改進(jìn)時(shí),將討論這些標記的示例以及如何將 Ajax4jsf 與 Eclipse 進(jìn)行集成。接下來(lái),將學(xué)習組成這個(gè)庫的每個(gè)組件、在使用它時(shí)必須記住的限制以及如何在 Eclipse 項目中添加 Ajax4jsf。
組件
Ajax4jsf 組件被設計成可以輕松地與現有的 JSF 應用程序進(jìn)行集成,同時(shí)提供了改進(jìn)性能的 Ajax 功能。表 1 中描述了 Ajax4jsf 庫中包含的所有標記。
表 1. Ajax4jsf 庫標記
| Ajax4jsf 組件 | 描述 |
| <a4j:actionListener> | 其效果類(lèi)似于 JSF 中的 <f:actionListener> 或 <f:valueChangeListener> 標記,但是它用于 Ajax 容器。 |
| <a4j:actionparam> | 結合了 <f:actionListener> 和 <f:param> JSF 標記的功能。 |
| <a4j:commandButton> | 效果類(lèi)似于被點(diǎn)擊時(shí)的表單 Submit 按鈕,但是呈現為 HTML <input> 標記。 |
| <a4j:commandLink> | 效果類(lèi)似于被點(diǎn)擊時(shí)的表單 Submit 按鈕,但是呈現為 HTML <a> 錨標記。 |
| <a4j:loadBundle> | 裝載當前視圖的本地化資源束。 |
| <a4j:mediaOutput> | 允許創(chuàng )建動(dòng)態(tài)生成的內容。 |
| <a4j:outputPanel> | 在頁(yè)面上創(chuàng )建一個(gè)啟用 Ajax 的部分,允許這個(gè)區域中的內容重新呈現(即使導致 Ajax 請求的組件沒(méi)有專(zhuān)門(mén)提到這個(gè)區域)。 |
| <a4j:page> | 呈現完整的 HTML 頁(yè)面結構。但是,它必須是 JSF <f:view> 標記的第一個(gè)和惟一的子元素,在它外邊不能有 HTML 代碼。 |
| <a4j:region> | 決定 JSF <f:view> 的哪個(gè)部分將通過(guò)為相關(guān)聯(lián)的 Ajax 請求提供內容來(lái)處理。這會(huì )只更新頁(yè)面中需要更新的部分,從而改進(jìn)性能。 |
| <a4j:status> | 通過(guò)指出請求何時(shí)開(kāi)始或結束,提供關(guān)于指定區域的 Ajax 請求的客戶(hù)端狀態(tài)。 |
| <a4j:support> | 將 Ajax 功能添加到與 JSF 相關(guān)的組件中。這個(gè)標記可能是最常用的。 |
根據場(chǎng)景,某些組件會(huì )比其他組件更常用。接下來(lái),將學(xué)習在使用 Ajax4jsf 時(shí)必須記住的條件。
條件
根據 Ajax4jsf 文檔所述,開(kāi)發(fā)人員必須記住某些限制才能創(chuàng )建正確的 Ajax 和 JSF 應用程序:
Ajax4jsf 框架并不在頁(yè)面上追加或刪除元素,它只會(huì )替換頁(yè)面上的元素。要想在頁(yè)面上追加代碼,應該使用一個(gè)空元素標出它的位置。
應該只創(chuàng )建嚴格的符合標準的 HTML 和 XHTML 代碼,不要省略任何必需的元素或屬性,因為 Ajax 請求由 XMLHttpRequest 函數以 XML 格式創(chuàng )建。但是,這些請求的 XML 格式可能會(huì )避開(kāi)瀏覽器中的大多數檢驗和任何糾正處理。
最后,大多數 Ajax4jsf 標記有一個(gè)屬性,它指定在發(fā)出 Ajax 請求之后要處理的元素的 ID。這些元素的 ID 必須匹配在 Ajax4jsf 標記的屬性中指定的 ID,只有這樣更新才會(huì )成功。
既然已經(jīng)了解了組件和使用 Ajax4jsf 的條件,就需要將這個(gè)庫添加到 Eclipse 項目中,然后才能對 Developer Forum Signup 應用程序進(jìn)行改進(jìn)。
將 Ajax4jsf 添加到 Eclipse 項目中
本教程中的 第 2 部分 介紹了將 Tomahawk 作為 JSF 組件庫添加進(jìn)項目中的步驟。使用同樣的步驟將 Ajax 作為 JSF 組件庫添加進(jìn)項目中。
右擊 devSignup 項目,并在上下文菜單中選擇 Properties。Eclipse 顯示 Properties 對話(huà)框,見(jiàn) 圖 1。
圖 1. devSignup 的 Properties 對話(huà)框

訪(fǎng)問(wèn) JSF Library References 面板,見(jiàn) 圖 2。
圖 2. JSF Library References 面板

點(diǎn)擊面板中間偏下的 Component Libraries 部分中的 New 按鈕,顯示 Create JSF Library 對話(huà)框(見(jiàn) 圖 3)。
在 Library Name 字段中輸入庫名(例如,Ajax4jsf)。
圖 3. Create JSF Library 窗口

點(diǎn)擊 Add 按鈕,然后選擇發(fā)布版存檔中的以下 Ajax4jsf JAR:
ajax4jsf.jar
oscache-2.3.2.jar
根據需要重復這個(gè)步驟。
點(diǎn)擊 Finish 將新的 Ajax4jsf 庫添加到項目 Properties 的 JSF Library References 面板中的列表中。這個(gè)新的 Ajax4jsf 庫添加到右邊的列表中,它會(huì )自動(dòng)地包含在項目的 .war 文件中?,F在對話(huà)框應該與 圖 4 相似。
點(diǎn)擊 OK 應用修改并關(guān)閉項目 Properties 對話(huà)框。
圖 4. Ajax4jsf 和 Tomahawk 作為組件庫列出

為了啟用 Ajax4jsf 組件,必須在應用程序的 web.xml 文件中聲明相應的 <filter> 標記。
打開(kāi) devSignup 項目下面的 WebContent/WEB-INF/web.xml。如果編輯器仍然處于 Design 模式,那么必須點(diǎn)擊編輯器底部的 Source 選項卡,切換到 Source 模式。
將 清單 1 中的代碼添加到 web.xml 文件中。<filter> 和 <filter-mapping> 元素應該是 <web-app> 元素的子元素。
清單 1. 在 web.xml 中啟用 Ajax4jsf 組件
<filter>
<display-name>Ajax4jsf Filter</display-name>
<filter-name>ajax4jsf</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>ajax4jsf</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
一定要將 <filter> 和 <filter-mapping> 標記放在 web.xml 文件中其他任何過(guò)濾器的前面。根據文檔所述,必須這樣做才能防止 web.xml 中其他任何過(guò)濾器與 Ajax4jsf 沖突。
<filter> 元素僅僅聲明 Ajax4jsf 過(guò)濾器類(lèi)。<filter-mapping> 元素將 Ajax4jsf 過(guò)濾器與這個(gè)文件中其他地方聲明的 Faces Servlet 關(guān)聯(lián)起來(lái)。
既然已經(jīng)在項目中添加并配置了 Ajax4jsf,就可以開(kāi)始改進(jìn) Developer Forum Signup 應用程序了。下一節通過(guò)討論 Temperature Conversion 實(shí)用程序的細節來(lái)討論這個(gè)問(wèn)題。
Temperature Conversion 實(shí)用程序
對于在 Developer Forum 應用程序中登錄后的成員,提供 Temperature Conversion 實(shí)用程序作為實(shí)際功能。這個(gè)實(shí)用程序將溫度從攝氏溫度轉換為華氏溫度,或者相反。每種溫度轉換的結果顯示為一個(gè)動(dòng)態(tài)生成的溫度計圖像。首先,學(xué)習如何用 Ajax4jsf 實(shí)現這個(gè)用戶(hù)界面。然后,看看實(shí)現這個(gè)實(shí)用程序的 bean。
使用 Ajax4jsf 實(shí)現溫度轉換器頁(yè)面
本系列的 第 2 部分 擴展了 Developer Forum Signup 應用程序,添加了字段驗證器和彈出式日歷來(lái)幫助用戶(hù)選擇生日。這些改進(jìn)都集中在注冊頁(yè)面上?,F在,將創(chuàng )建一個(gè)新頁(yè)面,它允許用戶(hù)輸入攝氏或華氏溫度,然后就會(huì )看到轉換后的溫度顯示為數字和圖像。
首先,需要提供一個(gè)鏈接,它允許成員在成功登錄之后訪(fǎng)問(wèn)這個(gè)實(shí)用程序。更新后的 signup-success.jsp 頁(yè)面使用與 清單 2 相似的一行代碼提供這個(gè)鏈接。
清單 2. 更新后的 signup-success 頁(yè)面的部分清單
*New* The Temperature Converter is
<a href="temperature-converter.faces">here</a>!
這個(gè)清單中惟一有意思的東西是溫度轉換器頁(yè)面的擴展名。在 Eclipse 中,這個(gè)文件實(shí)現為 JSP。當部署這個(gè)頁(yè)面時(shí),必須用 .faces 擴展名引用它,從而讓 Faces Servlet 處理它。
現在看看溫度轉換器頁(yè)面的實(shí)現。清單 3 中給出這個(gè)頁(yè)面的部分清單。
清單 3. temperature-converter.jsp 的部分清單
<%@ taglib uri="https://ajax4jsf.dev.java.net/ajax" prefix="a4j"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Temperature Converter</title>
</head>
<body>
<h1>Temperature Converter</h1>
<hr/>
<p>The Temperature Converter is provided as a benefit for our
members in the Developer Forum!</p>
<f:view>
<a4j:region id="CtoF" selfRendered="true">
<a4j:mediaOutput element="img" cacheable="false" session="true"
createContent="#{temperature.drawFahrenheitThermometer}"
value="#{thermometer}" mimeType="image/jpeg" />
<a4j:status startText="Processing..." stopText="" for="CtoF"/>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Temperature in Fahrenheit:" />
<h:outputText id="tempFahr"
value="#{temperature.outputFahrenheit}"/>
<h:outputText value="Temperature in Celsius:" />
<h:inputText size="5" value="#{temperature.inputCelsius}">
<a4j:support event="onkeyup" reRender="tempFahr" />
</h:inputText>
</h:panelGrid>
</h:form>
</a4j:region>
</f:view>
<hr/>
<p>Thank you for using the Temperature Converter!</p>
</body>
</html>
這個(gè) JSP 清單中有幾個(gè)有意思的元素。第一個(gè)是開(kāi)頭的 a4j <taglib> 聲明。對于任何使用 Ajax4jsf 組件庫的 JSP,這個(gè)聲明都是必需的。
<a4j:region> 標記聲明 Ajax 區域的開(kāi)頭和結尾。selfRendered 屬性設置為 true,這意味著(zhù)當發(fā)出相關(guān)聯(lián)的 Ajax 請求時(shí)將處理這個(gè)區域。
<a4j:mediaOutput> 標記允許創(chuàng )建動(dòng)態(tài)生成的內容,在這個(gè)示例中就是反映轉換后的華氏溫度的溫度計圖像。createContent 屬性指定負責創(chuàng )建此內容的 bean 方法。value 屬性指定一個(gè)對象,這個(gè)對象包含著(zhù) createContent 中的 bean 方法所需的數據。注意,value 中的數據對象必須實(shí)現 java.io.Serializable 類(lèi)。
<a4j:status> 標記提供 Ajax 請求的客戶(hù)端狀態(tài)。當請求開(kāi)始時(shí),顯示消息 "Processing..."。當請求停止時(shí),不顯示消息。for 屬性將這個(gè)狀態(tài)與指定的 ID 關(guān)聯(lián)起來(lái)。這正好是前面定義的 "CtoF" 區域。
最后,<a4j:support> 標記將 Ajax 支持添加到 JSF <h:inputText> 標記中。event 屬性指出哪個(gè) JavaScript 事件將觸發(fā) Ajax 請求。reRender 屬性包含在發(fā)出請求之后將重新呈現的對象的 ID 列表。在這個(gè)示例中,當用戶(hù)輸入攝氏溫度值時(shí),在每次釋放鍵盤(pán)鍵之后,發(fā)出一個(gè) Ajax 請求,從而用轉換后的華氏溫度重新呈現匹配的 JSF <h:outputText> 標記。圖 5 給出頁(yè)面的樣子。
圖 5. 運行時(shí)的 Temperature Conversion 實(shí)用程序

這就是在溫度轉換器頁(yè)面上使用 Ajax 的方式。正如 清單 3 所示,這個(gè)庫提供的組件很容易與 JSF 標記進(jìn)行集成。接下來(lái),研究一下處理實(shí)際溫度轉換和圖像創(chuàng )建的代碼。
溫度轉換器 bean
溫度轉換器 bean 是實(shí)現 Temperature Conversion 實(shí)用程序的模塊。負責進(jìn)行溫度轉換和圖像創(chuàng )建的所有方法都保存在 TemperatureConverter.java 文件中。下面幾個(gè)清單給出令人感興趣的幾個(gè)方法,首先是 清單 4。
清單 4. 對輸入的溫度進(jìn)行轉換
public void setInputCelsius(String inputCelsius)
{
Float tmpCelsius = null;
this.inputCelsius = inputCelsius;
// convert C to F
tmpCelsius = new Float(inputCelsius);
fahrenheitValue = new Float(celsiusToFahrenheit(tmpCelsius.floatValue()));
setOutputFahrenheit(fahrenheitValue.toString());
} // end setInputCelsius
public void setInputFahrenheit(String inputFahrenheit)
{
Float tmpFahrenheit = null;
this.inputFahrenheit = inputFahrenheit;
// convert F to C
tmpFahrenheit = new Float(inputFahrenheit);
celsiusValue = new Float(fahrenheitToCelsius(tmpFahrenheit.floatValue()));
setOutputCelsius(celsiusValue.toString());
} // end setInputFahrenheit
當用戶(hù)在溫度轉換器頁(yè)面上的文本字段中輸入一個(gè)值之后,會(huì )調用對應的 set 方法。這些方法調用代碼來(lái)轉換對應的溫度并相應地設置輸出值。清單 5 給出實(shí)際的轉換公式。
清單 5. 包含轉換公式的支持方法
private float celsiusToFahrenheit(float celsius)
{
float fahrenheit = 0.0f;
fahrenheit = ((9.0f / 5.0f) * celsius) + 32.0f;
System.out.println("celsius: " + celsius + "\tfahrenheit: "
+ fahrenheit);
return fahrenheit;
} // end celsiusToFahrenheit
private float fahrenheitToCelsius(float fahrenheit)
{
float celsius = 0.0f;
celsius = (5.0f / 9.0f) * (fahrenheit - 32.0f);
System.out.println("fahrenheit: " + fahrenheit + "\tcelsius: "
+ celsius);
return celsius;
} // end fahrenheitToCelsius
這兩個(gè)方法相當簡(jiǎn)單明了。輸入一個(gè)溫度,輸出轉換后的溫度。System.out.println 語(yǔ)句在啟動(dòng)時(shí)顯示的 Geronimo 控制臺上顯示字符串。這適合進(jìn)行快速調試,但是真正的日志記錄實(shí)用程序適合更復雜的應用程序。清單 6 包含負責創(chuàng )建華氏溫度計圖像的方法。
清單 6. 生成華氏溫度計圖像的方法
public void drawFahrenheitThermometer(OutputStream out, Object object)
throws IOException
{
BufferedImage thermometerImage = null;
Graphics2D image = null;
Thermometer thermometer = null;
if (object instanceof Thermometer)
{
thermometer = (Thermometer) object;
}
else
{
return;
} // end if
thermometerImage = new BufferedImage(
thermometer.getWidth().intValue(),
thermometer.getHeight().intValue(),
BufferedImage.TYPE_INT_RGB);
image = thermometerImage.createGraphics();
image.setBackground(thermometer.getThermometerColor());
image.clearRect(0, 0, thermometer.getWidth().intValue(),
thermometer.getHeight().intValue());
drawMercury(fahrenheitValue, thermometer, image);
drawThermometerUnits(thermometer, image);
ImageIO.write(thermometerImage, "jpeg", out);
} // end drawFahrenheitThermometer
這就是在 <a4j:mediaOutput> 的 createContent 屬性中指定的方法。它需要兩個(gè)參數,而且 Object 類(lèi)型的第二個(gè)參數必須實(shí)現 java.io.Serializable。這個(gè)方法使用標準的 Java 2D 圖形庫來(lái)創(chuàng )建溫度計圖像。尺寸存儲在數據對象 thermometer 中。drawMercury 和 drawThermometerUnits 方法見(jiàn) 清單 7。
清單 7. 繪制刻度和更新水銀柱的支持方法
private void drawThermometerUnits(Thermometer thermo, Graphics2D image2D)
{
Integer tmpInteger = null;
int blockCounter = 0;
int textCounter = 0;
int unitCounter = 0;
for (int x = 0; x < thermo.getWidth().intValue(); x++)
{
if (x == blockCounter)
{
image2D.drawLine(x,0,x,30);
tmpInteger = new Integer(textCounter);
image2D.setColor(thermo.getThermometerTextColor());
image2D.drawChars(tmpInteger.toString().toCharArray(),
0, tmpInteger.toString().length(), x, 45);
blockCounter = blockCounter + BLOCK_INCREMENT;
textCounter = textCounter + TEXT_INCREMENT;
unitCounter = unitCounter + UNIT_INCREMENT;
}
else if (x == unitCounter)
{
image2D.drawLine(x, 0, x, 10);
unitCounter = unitCounter + UNIT_INCREMENT;
} // end if
} // end for
} // end drawThermometerUnits
private void drawMercury(Float temperature, Thermometer thermo, Graphics2D image2D)
{
int mercuryValue = 0;
if (temperature == null)
{
temperature = new Float(0.0f);
} // end if
// Scale temperature to thermometer units in image2D
mercuryValue = temperature.intValue() * SCALE_TEMP;
image2D.setColor(thermo.getMercuryColor());
image2D.fill3DRect(0, 11, mercuryValue,
thermo.getMercuryHeight().intValue(), true);
System.out.println("temp.intVal: " + temperature.intValue() +
"\t" + "mercuryValue: " + mercuryValue);
} // end drawMercury
drawThermometerUnits 方法繪制溫度計的刻度來(lái)表示單位。這個(gè)方法逐一處理圖像寬度上的每個(gè)像素。每隔一定的間距,繪制一條短刻度線(xiàn)或長(cháng)刻度線(xiàn)。短刻度線(xiàn)代表 2 度,長(cháng)刻度線(xiàn)代表 10 度并在它下面繪制對應的數字。drawMercury 方法將轉換后的溫度乘以一個(gè)縮放因子,得出要繪制的水銀柱的像素數。
這就是轉換溫度和創(chuàng )建溫度計圖像所需的代碼。清單 8 給出數據對象 Thermometer.java。這個(gè)支持 bean 包含創(chuàng )建溫度計圖像所需的圖像信息。
清單 8. Thermometer.java 數據對象的部分清單
// Thermometer.java - Contains dimensions and color for thermometer
// image
package devSignup;
import java.awt.Color;
import java.io.Serializable;
public class Thermometer implements Serializable
{
private static final long serialVersionUID = 1L;
private static final int MERCURY_HEIGHT = 20;
private static final int THERMOMETER_WIDTH = 600;
private static final int THERMOMETER_HEIGHT = 50;
private Color thermometerColor = new Color(235, 235, 235);
private Color thermometerTextColor = new Color(0, 0, 0);
private Color mercuryColor = new Color(135, 135, 135);
private Integer mercuryValue = null;
private Integer mercuryHeight = null;
private Integer thermometerWidth = null;
private Integer thermometerHeight = null;
public Thermometer()
{
mercuryValue = new Integer(0);
mercuryHeight = new Integer(MERCURY_HEIGHT);
thermometerWidth = new Integer(THERMOMETER_WIDTH);
thermometerHeight = new Integer(THERMOMETER_HEIGHT);
} // end Thermometer
public Color getThermometerColor()
{
return thermometerColor;
} // end getThermometerColor
// ...additional get/set methods trimmed here...
public void setThermometerColor(Color thermometerColor)
{
this.thermometerColor = thermometerColor;
} // end setThermometerColor
} // end Thermometer
Thermometer 就是 <a4j:mediaOutput> 標記的 value 屬性中指定的數據對象。正如前面提到的,這個(gè)數據對象必須實(shí)現 Serializable Java 類(lèi)。注意,溫度計圖像所需的所有顏色和尺寸都在這個(gè)模塊中定義,但是 mercuryValue 除外。這個(gè)值實(shí)際上是未定義的,因為它是惟一一個(gè)根據用戶(hù)輸入而改變的值。
在使用這兩個(gè) bean 之前,需要在 faces-config.xml 部署描述符中定義它們。打開(kāi)這個(gè)文件,確保選擇 Source 選項卡。確保在這個(gè)文件中輸入 清單 9 的內容。
清單 9. 更新的 faces-config.xml 內容
<managed-bean>
<description>Temperature Converter Bean</description>
<managed-bean-name>temperature</managed-bean-name>
<managed-bean-class>devSignup.TemperatureConverter</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<description>Thermometer Bean</description>
<managed-bean-name>thermometer</managed-bean-name>
<managed-bean-class>devSignup.Thermometer</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
這兩個(gè)標記聲明兩個(gè) bean 并讓它們在被調用時(shí)對 JSF 庫可用。這樣就行了!Temperature Conversion 實(shí)用程序現在已經(jīng)可以進(jìn)行構建并部署到 Geronimo 上了,下面就來(lái)完成這些任務(wù)。
測試和故障排除
本節簡(jiǎn)要地討論如何構建和部署 Temperature Conversion 實(shí)用程序并在 Developer Forum 應用程序中訪(fǎng)問(wèn)它。還討論在開(kāi)發(fā)期間遇到的一些問(wèn)題。
測試
首先需要在 Eclipse 中構建示例應用程序。
右擊 devSignup 項目,然后選擇 Build Project。
在 Eclipse 編譯并驗證代碼之后,再次右擊 devSignup 項目。這一次選擇 Export。
在 Export 窗口中,展開(kāi) Web 文件夾,選擇 WAR file 并點(diǎn)擊 Next。
在 WAR Export 面板中,點(diǎn)擊 Browse 選擇一個(gè)目標,輸入 Web 存檔的文件名(例如,devSignup.war)并點(diǎn)擊 Save。
返回 WAR Export 面板之后,點(diǎn)擊 Finish 導出 .war 文件。如果需要的話(huà),選中覆蓋現有文件的復選框。
既然已經(jīng)將示例應用程序導出為 Web 存檔,就可以將它部署到 Geronimo 上了。有兩種部署方法:熱部署和通過(guò) Geronimo 的 Console 應用程序進(jìn)行部署。在 geronimo-1.1 安裝文件夾下面有一個(gè)稱(chēng)為 deploy 的文件夾。復制到這個(gè)文件夾中的任何存檔文件(比如 EAR 或 WAR)都由 Geronimo 自動(dòng)地進(jìn)行部署。反之,如果從這個(gè)目錄中刪除存檔文件,那么 Geronimo 就會(huì )卸載它們。前面的教程使用 Console 應用程序,所以我們繼續使用這種部署方法。
改進(jìn)后的 Developer Forum 應用程序已經(jīng)準備好了。用 URL http://localhost:8080/devSignup 訪(fǎng)問(wèn)這個(gè)應用程序。
第一個(gè)頁(yè)面與 第 2 部分 中創(chuàng )建的注冊頁(yè)面相同。創(chuàng )建一個(gè)論壇賬號。成功之后,向用戶(hù)顯示一個(gè)與 圖 6 相似的屏幕。
圖 6. 成功!

在這個(gè)頁(yè)面上,論壇成員現在可以點(diǎn)擊 here 鏈接來(lái)訪(fǎng)問(wèn) Temperature Conversion 實(shí)用程序。在訪(fǎng)問(wèn)這個(gè)實(shí)用程序之后,輸入攝氏或華氏溫度值。應該會(huì )出現兩個(gè)現象。首先,在輸入每個(gè)值之后,溫度立刻被轉換。其次,在輸入值時(shí),在溫度計旁邊顯示狀態(tài)消息 Processing...。在輸入所希望的溫度之后,按 Enter 鍵來(lái)更新溫度計圖像。恭喜!Ajax4jsf 提供的 Ajax 功能已經(jīng)發(fā)揮作用了。
故障排除
請您自己試試。但是要記住兩個(gè)問(wèn)題。正如前面所提到的,Ajax4jsf 的過(guò)濾器必須列在 web.xml 描述符文件中其他任何過(guò)濾器的前面。必須這樣做才能防止同一個(gè)文件中聲明的其他任何過(guò)濾器與 Ajax4jsf 過(guò)濾器沖突。根據文檔所述,這個(gè)條件和解決方案只適用于在 Apache MyFaces 中使用 Ajax4jsf。
Geronimo 提供了兩種部署應用程序的方法:熱部署和 Geronimo Console。這兩種機制看起來(lái)是相互獨立工作的。當總是只使用其中一種方法進(jìn)行部署時(shí),開(kāi)發(fā)人員很容易管理應用程序的安裝。但是,熱部署的應用程序不會(huì )出現在 Geronimo Console 的 Web App WAR 鏈接中。同樣,通過(guò) Geronimo Console 的 Deploy New 鏈接部署的應用程序也不會(huì )出現在為熱部署保留的 geronimo-1.1/deploy 文件夾中。因此,有可能在 Geronimo 上部署了同一應用程序的多個(gè)實(shí)例,而您卻不知道。這種情況可能會(huì )導致不可預測的結果。強烈建議您選擇一種部署方法并堅持使用它。
結束語(yǔ)
在這個(gè)教程中,通過(guò)添加 Temperature Conversion 實(shí)用程序改進(jìn)了 Developer Forum Signup 應用程序。我們研究了 Ajax4jsf 庫并使用幾個(gè) Ajax4jsf 組件創(chuàng )建了一個(gè)啟用 Ajax 的前端。還學(xué)習了如何將這個(gè)庫添加到 Eclipse Web 應用程序項目中。
本系列的第 4 部分將研究 Oracle 的 ADF Faces,這是構建于 JSF 之上的另一組 UI 組件,它最近被捐獻給了 Apache。這個(gè)教程將講解如何集成這個(gè)庫中的組件,從而進(jìn)一步改進(jìn) Developer Forum Signup 應用程序。敬請期待!
下載
| 描述 | 名字 | 大小 | 下載方法 |
| 第 3 部分源代碼 | devSignup-p3src.zip | 19KB | HTTP |
| 第 3 部分 WAR 文件 | devsignup-p3war.zip | 4240KB | HTTP |
聯(lián)系客服