在Java EE 6中使用JSF 2.0簡(jiǎn)化頁面制作
原創(chuàng)【51CTO精選譯文】過去幾個(gè)星期,51CTO對(duì)Java EE 6的新特性進(jìn)行了一系列介紹。除了Servlet 3.0的特性,Java EE 6也使用了新的JSF 2.0標(biāo)準(zhǔn)。下面我們來看一看JSF 2.0是如何簡(jiǎn)化頁面制作并提供Ajax支持的。***,我們對(duì)Servlet 3.0和JSF 2.0的新特性進(jìn)行了總結(jié)。
簡(jiǎn)化JSF 2.0頁面制作
JavaServer Faces技術(shù)提供了一個(gè)服務(wù)端組件框架,簡(jiǎn)化了Java EE應(yīng)用程序用戶界面的開發(fā),其中最顯著的改進(jìn)是頁面制作,通過使用標(biāo)準(zhǔn)的JavaServer Faces視圖聲明語言(JavaServer Faces View Declaration Language,俗稱Facelets)創(chuàng)建一個(gè)JSF頁面更加容易。
Facelets
Facelets是一個(gè)強(qiáng)大的輕量級(jí)聲明語言,可以使用它展示一個(gè)JSF頁面,使用Facelets時(shí),你可以使用HTML風(fēng)格的模板展示一個(gè)JSF頁面,也可以構(gòu)建一個(gè)組件樹,JSF應(yīng)用程序中的用戶界面通常是由JSF組件構(gòu)成的JSF頁面,F(xiàn)acelets在JSP之上提供了更多優(yōu)點(diǎn)。
在JSP中,Web頁面中的元素是按照漸進(jìn)順序處理和渲染的,而JSF提供了它自己的處理和渲染順序,這可能會(huì)導(dǎo)致不可預(yù)測(cè)的行為發(fā)生,F(xiàn)acelets解決了這個(gè)問題,通過模板,F(xiàn)acelets也允許代碼復(fù)用,可以大大減少開發(fā)UI的時(shí)間,現(xiàn)在Facelets已經(jīng)成為構(gòu)建JSF應(yīng)用程序的***技術(shù)。
Facelets通常是使用XHTML標(biāo)記語言編寫的,因此Facelets是可以跨不同開發(fā)平臺(tái)的,下面是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所示。
這個(gè)Facelets XHTML頁面和普通JSP頁面并沒有多大不同,F(xiàn)acelets支持JSF和JSTL標(biāo)簽庫,它也包括一個(gè)Facelets標(biāo)簽庫,支持功能豐富的頁面模板。命名空間聲明xmlns:ui="http://java.sun.com/jsf/facelets"就是針對(duì)facelets標(biāo)簽庫的,但這里沒有使用facelets標(biāo)簽庫的標(biāo)簽,facelets也支持統(tǒng)一的表達(dá)式語言。
模板
使用模板,你可以創(chuàng)建一個(gè)頁面作為應(yīng)用程序中其它頁面的模板,這樣可以避免多次創(chuàng)建結(jié)構(gòu)類似的頁面,同時(shí)也可以統(tǒng)一應(yīng)用程序中多個(gè)頁面的視覺風(fēng)格。
Facelets標(biāo)簽庫包括一個(gè)模板標(biāo)簽<ui:insert>,為了實(shí)施模板化,首先創(chuàng)建一個(gè)包括<ui:insert>標(biāo)簽的模板頁面,然后創(chuàng)建一個(gè)使用這個(gè)模板的客戶端頁面,在客戶端頁面中,使用<ui:composition>標(biāo)簽指定模板,使用<ui:define>標(biāo)簽指定插入到模板中的內(nèi)容。
下面是一個(gè)模板頁面的內(nèi)容:
- <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>
下面是使用這個(gè)模板的客戶端頁面代碼:
- <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>
當(dāng)客戶端調(diào)用這個(gè)模板時(shí),它使用標(biāo)題Welcome Page渲染這個(gè)頁面,這個(gè)頁面顯示了兩部分內(nèi)容,一個(gè)顯示客戶端中指定的鏈接列表,另一個(gè)顯示客戶端中指定的數(shù)據(jù)。
混合組件
混合組件時(shí)JSF中的一個(gè)新特性,通過它創(chuàng)建自定義JSF組件會(huì)更加容易。你可以使用JSF頁面標(biāo)記和其它JSF組件創(chuàng)建混合組件。在Facelets的標(biāo)注下,任何XHTML頁面都可以變成一個(gè)混合組件。此外,混合組件可以有驗(yàn)證器,轉(zhuǎn)換器和監(jiān)聽器。
創(chuàng)建好混合組件后,你可以將它保存到庫中,以后有需要時(shí)就可以調(diào)用了。
讓我們創(chuàng)建一個(gè)渲染為登錄面板的混合組件,用戶登錄時(shí),組件反饋一個(gè)登錄事件,如圖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>標(biāo)簽聲明混合組件的使用契約,<composite:attribute>標(biāo)簽在使用契約中指定<composite:actionSource>標(biāo)簽,這個(gè)表示組件可以暴露一個(gè)事件,讓使用這個(gè)混合組件的頁面可以輕松訪問它。
<composite:implementation>標(biāo)簽定義了混合組件的實(shí)現(xiàn),這里的實(shí)現(xiàn)是一個(gè)簡(jiǎn)單的表,它包括用戶名、密碼和登錄按鈕JSF組件。
為了讓混合組件可用,將代碼保存為XHTML文件,將文件放到應(yīng)用程序根目錄下resources目錄的子目錄中即可。子目錄的名字可以采用包含混合組件的資源庫名字,JSF運(yùn)行時(shí)通過向混合組件的標(biāo)簽名后追加.xhtml后綴查找混合組件。例如,如果你將標(biāo)簽命名為loginPanel,那么保存為混合組件的文件名就是loginPanel.xhtml。然后你就可以在Web頁面中使用混合組件了,下面就是一個(gè)使用混合組件的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/開頭,使用資源庫的名稱結(jié)束。
<f:actionListener>
標(biāo)簽關(guān)聯(lián)混合組件的行為監(jiān)聽器,標(biāo)簽中的for屬性表示這個(gè)監(jiān)聽器是為混合組件上名為loginEvent行為事件準(zhǔn)備的,你需要編寫代碼來處理事件,例如:
- 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");
- }
- }
#p#
JSF 2.0對(duì)Ajax的支持
JSF 2.0天生就支持Ajax,利用Ajax技術(shù),Web應(yīng)用程序在后臺(tái)以異步的方式從服務(wù)器獲取數(shù)據(jù)。支持Ajax后,允許頁面局部刷新,允許選擇視圖中的一個(gè)組件進(jìn)行處理而不影響其它組件。
要在JSF中使用Ajax,需要訪問有資源標(biāo)識(shí)符的JavaScript資源jsf.js,它存在于javax.faces資源庫中,包含讓JSF與Ajax交互的JavaScript API,JavaScript API由一組標(biāo)準(zhǔn)的JavaScript函數(shù)組成,使JavaServer Faces框架中的Ajax操作變得簡(jiǎn)單了,你幾乎不用直接包括這個(gè)文件,當(dāng)你使用任何開啟Ajax的標(biāo)簽或組件時(shí),JSF會(huì)自動(dòng)包括它。然后你就可以使用<f:ajax>標(biāo)簽或調(diào)用JavaScript API中的函數(shù)了。
下面是一個(gè)使用<f:ajax>標(biāo)簽的示例:
- <h:commandButton id="button1">
- <f:ajax execute="..." render="..."/>
- </h:commandButton>
這里的<f:ajax>標(biāo)簽是嵌套在<h:commandButton>標(biāo)簽內(nèi)的,這樣會(huì)結(jié)合在execute屬性中指定的Ajax行為和<h:commandButton>標(biāo)簽呈現(xiàn)的命令按鈕,你也可以指定一個(gè)event屬性來識(shí)別JavaScript DOM事件,如果你不指定event屬性,JSF使用組件的默認(rèn)行為,這里的默認(rèn)行為是onclick,因此JSF結(jié)合execute屬性中指定的Ajax請(qǐng)求和呈現(xiàn)按鈕的onclick事件。用戶點(diǎn)擊該按鈕時(shí),JSF提交Ajax請(qǐng)求給服務(wù)器。
使用<f:ajax>標(biāo)簽的一個(gè)好處是不用在頁面中指定載入jsf.js,它會(huì)自動(dòng)為你載入,相比之下,如果你調(diào)用JavaScript API,首先需要使用<h:outputScript>讓jsf.js對(duì)當(dāng)前視圖可用,例如:
- <f:view contentType="text/html"/>
- <h:head>
- <meta...
- <title...
- </h:head>
- <h:body>
- ...
- <h:outputScript name="jsf.js" library="javax.faces" target="body"/>
- ...
- </h:body>
- ...
然后才可以使用JavaScript API中的函數(shù)產(chǎn)生Ajax請(qǐng)求。例如,你使用JavaScript函數(shù)jsf.ajax.request向服務(wù)器發(fā)送一個(gè)請(qǐng)求,如下面的代碼:
- <h:commandButton id="button1" value="submit">
- onclick="jsf.ajax.request(this,event);" />
代碼包括一個(gè)<h:commandButton>標(biāo)簽,它呈現(xiàn)為一個(gè)按鈕,用戶點(diǎn)擊這個(gè)按鈕時(shí),向服務(wù)器提交一個(gè)Ajax請(qǐng)求。
Servlet 3.0和JSF2.0中的更多新特性
Servlet 3.0中另一個(gè)新特性是允許你使用ServletContext類中的方法通過編程在Web應(yīng)用程序啟動(dòng)時(shí)向其添加Servlet和Servlet過濾器,使用addServlet()方法添加Servlet,使用addFilter()添加Servlet過濾器。結(jié)合可插拔式共享框架特性,Web框架可以在無開發(fā)人員介入的情況下實(shí)現(xiàn)自我配置。
#t#此外Servlet 3.0加入了許多安全特性,除了聲明安全外,Server 3.0通過HttpServletRequest接口提供了編程安全,例如,你可以在應(yīng)用程序中使用HttpServletRequest的authenticate()方法執(zhí)行用戶名和密碼的收集,或者使用login()方法指向容器驗(yàn)證一個(gè)非強(qiáng)制請(qǐng)求上下文中的請(qǐng)求調(diào)用者。有關(guān)Servlet 3.0的更多特性,請(qǐng)參閱JSR 315規(guī)范。
JSF 2.0中的一些額外增強(qiáng)與資源如何打包和處理有關(guān),JSF 2.0標(biāo)準(zhǔn)化了打包哪里的資源。所有資源都放在resources目錄或一個(gè)子目錄下,資源需要按順序正確地進(jìn)行渲染,例如CSS文件和JavaScript文件,圖3顯示了Netbeans中的一個(gè)JSF項(xiàng)目部分結(jié)構(gòu)及文件,注意其中的resources目錄,CSS和images目錄。
圖 3 JSF應(yīng)用程序中resources目錄下的資源
JSF 2.0也包括顯示和處理資源的API,使用javax.faces.application.Resource類顯示一個(gè)資源,使用javax.faces.application.ResourceHandler類創(chuàng)建資源的實(shí)例。有關(guān)JSF 2.0的更多信息,請(qǐng)參閱JSR 314規(guī)范。
【51CTO.com譯稿,非經(jīng)授權(quán)請(qǐng)勿轉(zhuǎn)載。合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com,且不得修改原文內(nèi)容?!?/p>
原文:Introducing the Java EE 6 Platform 作者:Ed Ort