本教學是五部分教學系列的第 2 部分。本教學講解 Apache Tomahawk。在這個系列的第 1 期中,介紹了 JavaServer Faces (JSF),並在 Apache Geronimo 上構建和成功地部署了一個簡單的 JSF 應用程式。JSF 是一種基於 Java 的新框架,它使 Java Platform, Enterprise Edition (Java EE) 應用程式圖形使用者介面 (GUI) 的構建工作變得更為容易。現在將研究 Apache Tomahawk(它提供了數個定製的 100% 與 JSF 相容的元件),並學習如何將它整合到應用程式來改進介面。
本教學向 Java 程式設計師講解如何使用 JSF 元件構建高度互動性的部署在 Apache Geronimo 上的 Java EE 應用程式。本教學假設讀者將使用 Eclipse IDE 作為開發平台。
本教學講解 Apache Tomahawk,這是一套可以改進 JSF 應用程式介面的補充元件。我們將新增一些輸入驗證器和其他輸入元件,從而進一步開發開發者論壇註冊頁面的前端。
本教學是關於使用 JSF 構建 Apache Geronimo 應用程式的五部分教學系列的第 2 部分。整個系列教學包括以下幾個部分:
為了學習本教學,需要有下列工具:
在建立 Web 應用程式時,Java Servlet 和 JavaServer Pages (JSP) 技術提供了一個強大的環境,但並沒有給出建立使用者介面 (UI) 的標準方法。您必須全靠自己來管理 JSP 頁面中所有表單的狀態,還必須把進來的 HTTP 請求分派給適當的事件處理程式。如果網站的 GUI 很複雜,隨應用程式而產生的複雜基礎設施最終會變得難以管理。此外,網站還會有些特有的行為以及其他一些細節問題,使得您構建的程式碼很難被重用。JSF 提供了一種簡化高層任務(例如 UI 元件的排列和重用)的現成工具,並能夠把元件的狀態和輸入處理與決定應用程式行為的物件關聯起來。
Apache Geronimo 是一個開放原始碼(採用 Apache Software Foundation 授權協議)的 Java EE 伺服器,其設計目的是盡可能增強應用程式的相容性和效能。它的當前版本(到寫本文時是 1.1 版)通過了 Sun 的 Java 2 Platform, Enterprise Edition (J2EE) 的 Technology Compatibility Kit (TCK) 測試,這意味著它符合 Sun 的規範,與 J2EE 伺服器完全相容。
與 Jetty 或 Tomcat Web 伺服器打包在一起時,Geronimo 非常易於啟用和運行,而且它已經部署了一個極其有用的管理介面應用程式。不需要以任何方式重新啟動或重新配置伺服器,就可以從管理控制台上傳並啟動 Web 應用程式。
Apache MyFaces 是第一個免費的開放原始碼的 JSF Web 應用程式框架實作。JSF 類似於流行的 Struts 框架,實現了模型-視圖-控制器 (MVC) 模式,但是它的一些特性是 Struts 沒有提供的。JSF 是由 Java Specification Request #127 (JSR 127) 規範所定義的,這個規範已經被 Web 應用程式行業的專家批准成為 Java Community Process (JCP) 規範。
Apache Tomahawk 在 JSF 規範包含的元件之外提供了一套額外的 JSF 元件,同時與任何符合 JSF 1.1 的實作(比如 MyFaces)100% 相容。
Eclipse 是按照一個可擴展的面向外掛的架構而構建的,它是一個開放原始碼的整合開發環境 (IDE)。因此,只要有這一個 IDE 就能夠支援做任何工作所需的幾乎任何語言、任務、平台和資料檔案。這樣的話,開發人員將可以從出色的 Java 開發支援和 WTP 專案的外掛中獲益。WTP 提供了支援 XML 的編輯器,它還提供了實驗性的 MyFaces 支援。
在第 1 部分中,使用 Geronimo 部署了一個簡單的用 MyFaces 撰寫的 Web 應用程式,它為您建立自己的 Web 應用程式提供了一個很好的開端。這個應用程式為一個假想的面向開發者的論壇處理註冊過程。
在下一節中,將回顧第一個教學中所做的工作,然後討論 Tomahawk 的元件並在註冊應用程式中新增幾個 Tomahawk 元件。
在第 1 部分中,介紹了 Apache Geronimo 和 JSF 標準的 MyFaces 實作。學習了如何使用 Eclipse IDE 建立新的 JSF 專案、將它匯出為 .war 檔案並將它部署在 Geronimo 伺服器上。還看到了如何使用 Eclipse 中的 Faces Configuration 編輯器將 JSP 處理結果連接到適當的回應檔案。
應該從第 1 部分下載 devSignup 範例專案,因為本教學後面將改進它。
devSignup 作為專案名,然後點擊 Finish 建立空專案。devSignup 專案,然後在右鍵選單中選擇 Import 顯示 Import 對話方塊。devSignup 專案的某些部分包含系統特有的資訊,比如安裝 Java 程式庫和 MyFaces JAR 的路徑。這也是用 Eclipse 共享專案時的常見問題。我們來查看專案的設置並修復需要修復的設置。
MyFaces (Core)。v1_1(因為 Apache MyFaces 支援 1.1 版的 JSF 規範),然後點擊 Add 按鈕,選擇要包含在這個程式庫定義裡的 JSF .jar 檔案。Tomahawk 專案將它的元件鬆散地劃分為三類:元件、驗證器和其他東西。我們來看看每一類給 JSF 應用程式開發人員提供了什麼,並展望一下它們對本系列的第一個教學中開發的 JSF Developer Forum Signup 應用程式能夠進行怎樣的擴展。
一個重要的細節是:許多這些元件需要包含圖形元素(比如圖像)或 JavaScript 程式碼。它們是 Tomahawk .jar 檔案的一部分,並自動地包含在 MyFaces Extensions Filter 的 JSP 輸出中。在下一節中,將學習如何安裝它,所以不必為缺少 Tomahawk 元件所需的圖像或 JavaScript 擔心。
大多數 Tomahawk 元件(見表 1)是擴展的或高級的使用者介面元件,其設計目的是使 Web 應用程式的外觀和感覺更接近一般的桌面應用程式。其中一些元件提供了極其複雜的圖形元件,如果您的應用程式中碰巧需要這樣的元件,那麼直接使用它們可以節省大量開發時間。
| 元件 | 描述 |
|---|---|
| Alias Bean (Data, <t:aliasBean>) | 允許為現有的 bean 建立別名。 |
| Buffer (Data, <t:buffer>) | 將頁面的一部分放進 bean 中,以便稍後顯示它。 |
| Calendar (Input, <t:inputCalendar>) | 顯示一個日曆,讓使用者可以輕鬆地選擇一個日期。周名稱、月名稱和每周的起始日是根據系統地區自動選擇的,所以本地化是自動的。 |
| Column (Column, <t:column>) | <h:column> 的擴展版本,提供了直通屬性,允許精確地控制如何顯示頁首、頁尾和資料儲存格,以及它們如何回應 JavaScript 事件。 |
| Columns (Data, <t:columns>) | 在 Data Table 中使用,在表中提供數量可以動態變化的欄。 |
| Data List (Data, <t:dataList>) | 與 Data Table 相似,但是將它的列顯示為簡單的逗號分隔清單、帶符號清單或編號清單。 |
| Data Scroller (Panel, <t:dataScroller>) | 這個控制項允許翻頁瀏覽 UIData(<h:dataTable>);它顯示 first、fast rewind、previous、next、fast forward 和 last 按鈕來控制顯示。 |
| Date (Input, <t:inputDate>) | 顯示一個用來輸入日期的文字輸入控制項。可以接受日期或時間(或同時接受這兩者),提供一個用來選擇日期的彈出日曆,處理 12 小時或 24 小時時間。 |
| Extended Data Table (Data, <t:dataTable>) | 擴展了標準的 JSF DataTable,能夠保存 DataModel 的狀態並支援可點擊的排序標題。 |
| File Upload (Input, <t:inputFileUpload>) | 顯示一個允許使用者上傳檔案的 HTML 輸入欄位。允許指定這個欄位接受哪種 Multipurpose Internet Mail Extensions (MIME) 類型。 |
| Html Editor (Input, <t:inputHtml>) | 顯示一個簡單的基於 HTML 的行內字處理程式。當前,在每個頁面上只能有一個 HTML 編輯器,但是如果每次只顯示一個編輯器,那麼可以使用選項卡包含多個編輯器。 |
| Html Tag (Output, <t:htmlTag>) | 顯示任何 HTML 標記。 |
| Javascript Listener (Output, <t:jsValueChangeListener>) | 在客戶端模擬 JavaScript 提供的 Value Change Listener 功能。 |
| JSCook Menu (Command, <t:jscookMenu>) | 顯示一個基於 JavaScript 的動態選單。 |
| Newspaper Table (Obsolete!) | 這個控制項已經廢棄了,所以不要使用它。Newspaper Table 的功能現在包含在 Extended Data Table 元件中。 |
| Panel Navigation (Panel, <t:panelNavigation>) | 顯示一個垂直選單並支援巢狀的選單項。 |
| Panel Navigation 2 (Panel, <t:panelNavigation2>) | 與 Panel Navigation 元件相似,但是使用無序清單而不是表進行顯示。還可以使用 Navigation Menu Items 動態地建立選單樹。 |
| Panel Stack (Panel, <t:panelStack>) | 顯示重疊的 Panel,允許動態地切換面板。 |
| Popup (Panel, <t:popup>) | 一個在發生滑鼠事件時顯示的彈出面板(比如當滑鼠指標停留在另一個使用者介面元件上時)。 |
| Schedule (Panel, <t:schedule>) | 與 Microsoft Outlook 客戶端或 Evolution 中的日程安排程式相似,在日、工作周、周或月視圖中顯示約會或活動安排。 |
| Style Sheet (Output, <t:stylesheet>) | 顯示常用 CSS 樣式表檔案的路徑。 |
| TabbedPane (Panel, <t:panelTabbedPane>) | 顯示一個分頁式的 Panel,允許使用者在 Panel 之間進行切換。 |
| Tree (HtmlTree, <t:tree>) | MyFaces 中 HTML 樹元件的擴展版本,允許為樹、節點和選擇的節點指定 CSS 類別。 |
| Tree2 (HtmlTree, <t:tree2>) | 一個高度可定製的擴展樹元件,它的資料由一個後端 bean 提供。 |
| Tree Table (HtmlTreeColumn, <t:tree>) | 顯示一個帶樹型欄的表。 |
| UI Save State (Data, <t:saveState>) | 允許對 bean 和值進行持久化,使其生命週期長於 Request 範圍,但是短於 Session 範圍。 |
顯然,其中一些元件非常有用,而其他元件可能只適用於很特殊的場景。
Tomahawk 還提供了幾個方便的驗證器(見表 2),可以用來確保輸入資料的品質。
| 驗證器 | 描述 |
|---|---|
| validateCreditCard (<t:validateCreditCard>) | 驗證 American Express、Discover、MasterCard 或 Visa 的信用卡資訊。還可以用來確定資料不是支援的信用卡之一。 |
| validateEmail (<t:validateEmail>) | 驗證電子郵件地址。 |
| validateEqual (<t:validateEqual>) | 確保這個元件中的資料與另一個元件中的資料匹配。適用於驗證密碼或電子郵件地址等資訊。 |
| validateRegExpr (<t:validateRegExpr>) | 確保這個元件中的資料與指定的正則表示式匹配。用來驗證全數字的欄位、電話號碼等資訊。 |
| validateUrl (<t:validateUrl>) | 驗證 URL。 |
透過重用這些驗證器,可以減少大量工作。正則表示式驗證器尤其靈活,只要能夠將所需的資料表示為正則表示式,就能夠進行驗證。
Tomahawk 還提供了對 JSF 開發人員有幫助的其他一些東西(見表 3),其中的擴展過濾器是在使用許多 Tomahawk 元件時都需要的。
| Tomahawk 內容 | 描述 |
|---|---|
| 擴展過濾器 | 一些 Tomahawk 元件需要對 JavaScript、CSS 樣式表和圖像的額外支援。這些資源包含在 Tomahawk .jar 檔案中,而擴展過濾器提供了從產生的 HTML 存取這些資源所需的程式碼和 URL。擴展過濾器還處理檔案上傳元件(<t:inputFileUpload>)所使用的多部分請求。 |
| forceId 屬性 | 可以為任何 Tomahawk 元件指定這個屬性,允許將這個 ID 設置為 ID 屬性指定的值。如果需要對特定的 HTML 元素 ID 使用 JavaScript 或 CSS 樣式,這個屬性就很有用。 |
| JspTilesViewHandler | Tomahawk 允許使用來自 Struts 應用程式的 tiles,從而能夠將現有的 tiles 整合到 JSF 應用程式中。 |
如果您還不是 Struts 開發人員,那麼擴展過濾器可能是這些東西中最重要的,因為許多 Tomahawk 元件都需要它。因為 Tomahawk 文件似乎沒有包含這方面的詳細資訊,所以如果要使用 Tomahawk 特性,最好總是使用擴展過濾器。幸運的是,使用它並不太影響效能。
在下一節中,將在 MyFaces 應用程式中使用 Tomahawk 並在 Eclipse 中用 Web Tools Platform 進行開發。
如果您像我一樣性急的話,現在可能迫不及待地想開始撰寫一些程式碼,試試這些方便的元件。首先,您應該仔細考慮一下在自己的 Web 應用程式中需要使用 Tomahawk 做什麼。接下來,我們對第一個教學中的 Developer Forum Signup 應用程式進行擴展,在其中利用一些 Tomahawk 元件。
將 Tomahawk 元件新增到 JSF 應用程式中是很簡單明瞭的。需要將一個資源新增到 Tomahawk .jar 檔案中、將擴展過濾器新增到 web.xml 檔案中並將 Tomahawk 標記程式庫包含到 JSF 頁面中。
Tomahawk),然後從 Version Supported 下拉清單中選擇 v1_1,因為 MyFaces 實作了 1.1 版的 JSF 規範。tomahawk-1.1.3.jar)。為了啟用 Tomahawk 擴展,需要將擴展過濾器新增到 Web 應用程式中。雙擊專案的 web.xml 檔案(位於 WebContent/WEB-INF 資料夾中),在 XML 編輯器中打開它。如果編輯器處於 Design 模式,就要點擊編輯器底部的 Source 選項卡,從而切換到 Source 模式,這樣就會看到原始的 XML 樹。
將下列程式碼新增到 web.xml 中;<filter> 和 <filter-mapping> 元素應該是 <web-app> 的子元素,而不是任何其他 web.xml 標記的子元素。
<filter>
<filter-name>MyFacesExtensionsFilter</filter-name>
<filter-class>
org.apache.myfaces.webapp.filter.ExtensionsFilter
</filter-class>
<init-param>
<param-name>maxFileSize</param-name>
<param-value>20m</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
</filter-mapping>
<filter> 元素新增 MyFaces 擴展過濾器類並將 maxFileSize 參數設定為 20MB。maxFileSize 是檔案上傳元件允許的最大大小,可以用位元組(一個數字)、千位元組(一個數字加上 k)、百萬位元組(一個數字加上 m)或十億位元組(一個數字加上 g)為單位來指定。
第一個 <filter-mapping> 元素將 MyFaces 擴展過濾器應用於指定的 servlet。<servlet-name> 必須與 web.xml 檔案中已有的 <servlet> 元素中指定的 servlet 名稱匹配。
第二個 <filter-mapping> 元素告訴 MyFaces 擴展過濾器在處理 Tomahawk 元件使用的額外 JavaScript、樣式表和圖像時要匹配哪些 URL。與這個模式匹配的 URL 被解釋和轉換為對 Tomahawk .jar 檔案中適當資源的引用。
需要做的最後一件事是在 .jsp 檔案中啟用 Tomahawk 擴展。將下列程式碼新增到每個使用 Tomahawk 元件的 JSP 頁面中。在 devSignup 專案中,只有 signup.jsp(回應頁面不使用任何 JSF 程式碼)。
<%@ taglib uri="https://myfaces.apache.org/tomahawk" prefix="t" %>
這樣就行了!現在已經可以在範例應用程式中使用 Tomahawk 元件了。
在第一個教學中建立的 Developer Forum Signup 應用程式非常簡單。它允許使用者輸入螢幕名、電子郵件地址和密碼。對資料沒有進行驗證,也沒有採用任何機制來確保使用者輸入的密碼沒有輸入錯誤。下列程式碼顯示主註冊頁面 signup.jsp 的當前狀態(注意,我已經在 <f:view> 元素前面新增了 Tomahawk 標記程式庫)。
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="https://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="https://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="https://myfaces.apache.org/tomahawk" prefix="t" %>
<f:view>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Developer Forum Signup</title>
</head>
<body>
<h1>Developer Forum Signup</h1>
<p>
Welcome to our forums! Please fill in the following form to create your
forum account.
</p>
<h:form>
<dl>
<dt>Screen name:</dt>
<dd>
<h:inputText value="#{signupData.screenName}"/>
</dd>
<dt>Email:</dt>
<dd>
<h:inputText value="#{signupData.email}"/>
</dd>
<dt>Password:</dt>
<dd>
<h:inputSecret value="#{signupData.password}"/>
</dd>
</dl>
<h:commandButton action="#{signupData.register}">Sign
up</h:commandButton>
</h:form>
</body>
</html>
</f:view>
這是一個簡單的頁面,它使用 MyFaces 元件收集使用者的資料並在 Sign up 按鈕被點擊時執行 signupData bean 的 register() 方法。
應該新增的一個東西是一個驗證器,用它確保使用者已經輸入了有效的電子郵件地址。編輯 devSignup 專案中的 signup.jsp(如果還沒有新增 Tomahawk 標記程式庫,那麼一定要記得新增它)並將 Email 欄位的 <h:input> 標記替換為下列程式碼:
<h:inputText value="#{signupData.email}" id="email" required="true">
<t:validateEmail/>
</h:inputText><br/>
<strong><h:message for="email"/></strong>
這就是需要做的所有工作。Tomahawk 會自動地檢查輸入的資料,確保它是有效的電子郵件地址。如果不是有效的電子郵件地址,那麼它將 ID email 的訊息設定為適當的錯誤訊息。如果有訊息,<h:message> 元素將顯示 ID email 的訊息(否則,它什麼都不顯示,所以只會在發生錯誤時看到這個訊息)。
例如,如果輸入 not!email 作為電子郵件地址,那麼在點擊 "Sign up" 按鈕之後可能看到類似下圖的結果。

圖 11. 輸入無效的電子郵件地址
表單會重新顯示。這一次,設定了 Email 欄位的訊息,所以它會顯示出來;看到了吧,正如我們預料的,這是一個錯誤訊息。
現在,應該要求使用者輸入密碼兩次;使用者看不到自己輸入的密碼,所以兩次輸入可以幫助使用者確保正確地輸入了想要設置的密碼。將下列程式碼新增到 Password 欄位的 </dd> 標記後面。這會新增第二個 Password 輸入欄位,而且使用者在這裡輸入的資料必須與第一個 Password 欄位的內容匹配。
<dt>Password (for verification):</dt>
<dd>
<h:inputSecret id="password_verify" required="true">
<t:validateEqual for="password"/>
</h:inputSecret><br/>
<strong><h:message for="password_verify"/></strong>
</dd>
這使用 <t:validateEqual> 確保內容是相同的,並使用 <h:message> 顯示與表單的這個部分相關聯的任何訊息。可以看到類似下圖的錯誤訊息。

圖 12. 輸入了兩個不匹配的密碼
可以看到,這個驗證器並不完善。但是,至少已經在註冊頁面中新增了一些出色的功能,而無需修改 Java 程式碼。
怎麼新增更酷一點兒的東西呢?向進行註冊的使用者詢問生日。可以使用這一資訊確保使用者超過了 18 歲(如果需要這麼做的話),還可以在適當的日子向使用者祝賀生日快樂。將下列程式碼新增到 signup.jsp 檔案中 </dl> 標記的前面。
<dt>Birthday:</dt>
<dd>
<t:inputDate id="birthday" value="#{signupData.birthday}" popupCalendar="true"/>
</dd>
下圖顯示生日提示和一個支援彈出式日曆的日期輸入控制項,這樣使用者就能夠用選擇的方法輸入生日而無需手工輸入。

圖 13. 新增生日提示和日期輸入控制項
因為要引用 signupData bean 的 date 成員,所以最終還必需修改一些 Java 程式碼。編輯 SignupData.java 檔案(在 devSignup 專案中 src/devSignup 下面),將下列程式碼新增到 SignupData 類別中。
private java.util.Date _birthday = null;
public SignupData() {
_birthday = new java.util.Date();
}
public java.util.Date getBirthday() {
return _birthday;
}
public void setBirthday( java.util.Date newBirthday ) {
this._birthday = newBirthday;
}
並不需要做很多工作,就能夠在 Web 頁面上新增如此複雜的資料輸入控制項!現在可以構建並部署這個 Web 應用程式,看看已經完成的成果。
我們已經做了幾處修改,現在是時候看看 Developer Signup 應用程式的效果了。需要構建這個專案、匯出 .war 檔案並將它部署到 Geronimo 伺服器上。
devSignup 專案,然後從選單中選擇 Project > Build Project。Eclipse 編譯 Java 程式碼並驗證 JSP 頁面和 XML 檔案。devSignup,然後從右鍵選單中選擇 Export。devSignup.war 保存到桌面,這樣在伺服器上部署它時很容易找到它。)https://localhost:8080/console/(如果您的 Geronimo 伺服器不在同一台機器上運行,那麼要用它的主機名替換 localhost)。這會顯示 Geronimo Console Login 畫面。server,預設密碼是 manager,應該修改它們。)現在,在造訪 Developer Signup 應用程式時(在我的系統上是 https://localhost:8080/devSignup/signup.faces,如果您的伺服器不在本地機器上運行,那麼要用伺服器的主機名替換 localhost),應該會看到類似下圖的介面。

圖 17. 改進後的應用程式
當使用者點擊 Birthday 輸入欄位旁邊的 ... 按鈕時,出現類似下圖的元件。(這個元件如此複雜,但是我們沒做多少工作就獲得了這種功能,對它的支援是自動的!)

圖 18. 日期輸入欄位的彈出式日曆
這非常酷,而且它完全是用 JavaScript 和 CSS 在客戶端系統上實現的。唯一的缺點是它看起來不太像 "本機" 應用程式。
好了!我們已經成功地掌握了 Apache Tomahawk 並使用它擴展了 Developer Signup Web 應用程式。
我們研究了 Apache Tomahawk 元件,討論了如何將它們新增到 Eclipse Web 應用程式專案中,並使用它們擴展了第一個教學中開發的 Developer Forum Signup 應用程式。
在本系列的下一期中,我們將在 JSF 應用程式中新增 Ajax 功能,使用它們讓 Developer Forum Signup 應用程式更具互動性,同時避免更多的頁面重載或轉移。
| 描述 | 名字 | 大小 | 下載方法 |
|---|---|---|---|
| 第 2 部分原始碼 | devSignup-src.zip | 11KB | HTTP |
| Signup2 應用程式 WAR 檔案 | devSignup-war.zip | 3160KB | HTTP |