【51CTO精選譯文】過去幾個星期,51CTO對Java EE 6的新特性進行了一系列介紹。除了Servlet 3.0的特性,Java EE 6也使用了新的JSF 2.0標准。下面我們來看一看JSF 2.0是如何簡化頁面制作並提供AJax支持的。最後,我們對Servlet 3.0和JSF 2.0的新特性進行了總結。
簡化JSF 2.0頁面制作
JavaServer Faces技術提供了一個服務端組件框架,簡化了Java EE應用程序用戶界面的開發,其中最顯著的改進是頁面制作,通過使用標准的JavaServer Faces視圖聲明語言(JavaServer Faces VIEw Declaration Language,俗稱Facelets)創建一個JSF頁面更加容易。
Facelets
Facelets是一個強大的輕量級聲明語言,可以使用它展示一個JSF頁面,使用Facelets時,你可以使用Html風格的模板展示一個JSF頁面,也可以構建一個組件樹,JSF應用程序中的用戶界面通常是由JSF組件構成的JSF頁面,Facelets在JSP之上提供了更多優點。
在JSP中,Web頁面中的元素是按照漸進順序處理和渲染的,而JSF提供了它自己的處理和渲染順序,這可能會導致不可預測的行為發生,Facelets解決了這個問題,通過模板,Facelets也允許代碼復用,可以大大減少開發UI的時間,現在Facelets已經成為構建JSF應用程序的首選技術。
Facelets通常是使用XHtml標記語言編寫的,因此Facelets是可以跨不同開發平台的,下面是Java EE 6教材中提供的JSF頁面的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" XML:lang="en" lang="en"
- XMLns:f="http://Java.sun.com/JSf/core"
- XMLns:h="http://Java.sun.com/JSf/Html"
- XMLns:ui="http://Java.sun.com/JSf/facelets">
- <head>
- <title>Guess Number JSF Application</title>
- </head>
- <body>
- <h:form>
- <h2>
- Hi. My name is Duke. I am thinking of a number from <b>
- <h:outputText value="#{UserNumberBean.minimum}"/> to
- <b>
- <h:outputText value="#{UserNumberBean.maximum}"/>.
- <p>
- Can you guess it ?
- </p>
- <h:graphicImage id="waveImg" url="/wave.med.gif" />
- <h:inputText id="userNo"
- value="#{UserNumberBean.userNumber}">
- converterMessage="#{ErrMsg.userNoConvert}">
- <f:validateLongRange
- minimum="#{UserNumberBean.minimum}"
- maximum="#{UserNumberBean.maximum}"/>
- </h:inputText>
- <h:commandButton id="submit"
- action="success" value="submit" />
- <h:message showSummary="true" showDetail="false"
- style="color: red;
- font-family: 'New Century Schoolbook', serif;
- font-style: oblique;
- text-decoration: overline"
- id="errors1"
- for="userNo"/>
- </h2>
- </h:form>
- </body>
- </Html>
頁面渲染效果如圖1所示。
圖 1 使用Facelets創建的用戶界面
這個Facelets XHtml頁面和普通JSP頁面並沒有多大不同,Facelets支持JSF和JSTL標簽庫,它也包括一個Facelets標簽庫,支持功能豐富的頁面模板。命名空間聲明XMLns:ui="http://Java.sun.com/JSf/facelets"就是針對facelets標簽庫的,但這裡沒有使用facelets標簽庫的標簽,facelets也支持統一的表達式語言。
模板
使用模板,你可以創建一個頁面作為應用程序中其它頁面的模板,這樣可以避免多次創建結構類似的頁面,同時也可以統一應用程序中多個頁面的視覺風格。
Facelets標簽庫包括一個模板標簽<ui:insert>,為了實施模板化,首先創建一個包括<ui:insert>標簽的模板頁面,然後創建一個使用這個模板的客戶端頁面,在客戶端頁面中,使用<ui:composition>標簽指定模板,使用<ui:define>標簽指定插入到模板中的內容。
下面是一個模板頁面的內容:
- <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:h="http://Java.sun.com/JSf/Html"
- <head>
- <title><ui:insert name="title">Page Title</ui:insert</title><body>
- </head>
- <body>
- <div>
- <ui:insert name="Links"/>
- </div>
- <div>
- <ui:insert name="Data"/>
- </div>
- </body>
- </Html>
下面是使用這個模板的客戶端頁面代碼:
- <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:h="http://Java.sun.com/JSf/Html"
- <body>
- <ui:composition template="/template.xHtml">
- This text will not be displayed.
- <ui:define name="title">
- Welcome page
- </ui:define>
- <ui:define name="Links">
- ... [Links should be here]
- </ui:define>
- <ui:define name="Links">
- ... [Data should be here]
- </ui:define>
- </ui:composition>
- This text also will not be displayed.
- </body>
- </Html>
當客戶端調用這個模板時,它使用標題Welcome Page渲染這個頁面,這個頁面顯示了兩部分內容,一個顯示客戶端中指定的鏈接列表,另一個顯示客戶端中指定的數據。
混合組件
混合組件時JSF中的一個新特性,通過它創建自定義JSF組件會更加容易。你可以使用JSF頁面標記和其它JSF組件創建混合組件。在Facelets的標注下,任何XHtml頁面都可以變成一個混合組件。此外,混合組件可以有驗證器,轉換器和監聽器。
創建好混合組件後,你可以將它保存到庫中,以後有需要時就可以調用了。
讓我們創建一個渲染為登錄面板的混合組件,用戶登錄時,組件反饋一個登錄事件,如圖2所示。
圖 2 登錄面板混合組件
下面是混合組件的源代碼:
- <!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:h="http://Java.sun.com/JSf/Html"
- XMLns:f="http://Java.sun.com/JSf/core">
- XMLns:f="http://Java.sun.com/JSf/facelets">
- XMLns:composite="http://Java.sun.com/JSf/composite">
- <h:head>
- <title>This content will not be displayed in the rendered output</title>
- </h:head>
- <h:body>
- <composite:interface>
- <composite:actionSource name="loginEvent"/>
- </composite:interface>
- <composite:implementation>
- <table>
- <tr>
- <td>Username: <h:inputText id="username" /> </td>
- </tr>
- <tr>
- <td>PassWord: <h:inputSecret id="passWord" /></td>
- </tr>
- <tr>
- <td><h:commandButton value="Login" id="loginEvent" /></td>
- </tr>
- </table>
- </composite:implementation>
- </h:body>
- </Html>
XMLns:composite="http://Java.sun.com/JSf/composite"聲明了混合UI組件的命名空間,<composite:interface>標簽聲明混合組件的使用契約,<composite:attribute>標簽在使用契約中指定<composite:actionSource>標簽,這個表示組件可以暴露一個事件,讓使用這個混合組件的頁面可以輕松訪問它。
<composite:implementation>標簽定義了混合組件的實現,這裡的實現是一個簡單的表,它包括用戶名、密碼和登錄按鈕JSF組件。
為了讓混合組件可用,將代碼保存為XHTML文件,將文件放到應用程序根目錄下resources目錄的子目錄中即可。子目錄的名字可以采用包含混合組件的資源庫名字,JSF運行時通過向混合組件的標簽名後追加.xhtml後綴查找混合組件。例如,如果你將標簽命名為loginPanel,那麼保存為混合組件的文件名就是loginPanel.xHtml。然後你就可以在Web頁面中使用混合組件了,下面就是一個使用混合組件的Web頁面代碼示例:
- <!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:h="http://Java.sun.com/JSf/Html"
- XMLns:f="http://Java.sun.com/JSf/core"
- XMLns:ui="http://Java.sun.com/JSf/facelets"
- XMLns:ez="http://Java.sun.com/JSf/composite/ezcomp">
- <head>
- <title>Example 01>/title>
- <style type="text/CSS">
- .grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; }
- </style>
- </h:head>
- <h:body>
- <p>Usage of Login Panel Component</p>
- <ui:debug hotkey="p" rendered="true"/>
- <h:form>
- <div id="compositeComponent" class="grayBox" style="border: 1px solid #090;">
- <ez:loginPanel>
- <f:actionListener for="loginEvent" type="example01.LoginActionListener" />
- </ez:loginPanel>
- </div>
- <p><h:commandButton value="reload" /></p>
- <p><h:outputText value="#{loginActionMessage}" /></p>
- </h:form>
- </h:body>
- </Html>
注意聲明XMLns:ez="http://java.sun.com/jsf/composite/ezcomp",它指定了混合組件的命名空間和前綴,這裡的ezcomp是資源目錄的子目錄名,JSF使用下面的約定:所有命名空間URI都以http://Java.sun.com/JSf/composite/開頭,使用資源庫的名稱結束。
<f:actionListener>
標簽關聯混合組件的行為監聽器,標簽中的for屬性表示這個監聽器是為混合組件上名為loginEvent行為事件准備的,你需要編寫代碼來處理事件,例如:
- import Javax.faces.component.UIComponent;
- import Javax.faces.component.ValueHolder;
- import Javax.faces.context.FacesContext;
- import Javax.faces.event.AbortProcessingException;
- import Javax.faces.event.ActionEvent;
- import Javax.faces.event.ActionListener;
- public class LoginActionListener implements ActionListener {
- public void processAction(ActionEvent event) throws AbortProcessingException {
- FacesContext context = FacesContext.getCurrentInstance();
- context.getExternalContext().getRequestMap().put("loginActionMessage",
- "Login event happened");
- }
- }