2010/01/25

Facelet

Facelet被使用的定位歸屬是JavaServer Face視圖解決框架,是一個為了JavaServer Faces技術所開發的頁面宣告
語言,在JavaServer Faces 2.0之後,Facelet已經是JavaServer Faces規範的其中一員,以及也被建議使用來建
立和表現JavaServer Faces為基本的應用程式。

JavaServer Page(JSP)技術,先前被JavaServer Faces用來做為表現的技術並不完全被支援在JSF 2.0裡的新特色。
JSP在JSF 2.0以後被認為是一種不合時宜的表現技術。

Facelets的優勢

對開發者開發大型專案時使用JSF作為平台,重複使用程式碼和減輕開發是重要的好處。藉由支援這些特色,Facelets減少了
時間和努力在發展和佈署。

Facelets優勢包含了下列幾項:

  • 支援程式碼重用透過模板和組合component
  • component和其他Server端物件透過客製化的功能延伸
  • 更快的編譯時間
  • 編譯時的EL驗證
  • 高效能的rendering

什麼是Facelets?

Facelets是一個很強的頁面宣告語言但是卻很輕,被用來建立JavaServer Faces視圖,使用HTML風格的模板和建立
component樹。

Facelets特色包含下列幾項:

  • 使用XHTML來製作網頁
  • 支援Facelets標籤庫,加上JSF和JSTL標籤庫
  • 支援統一表現語言(EL)
  • components和頁面的模板

網頁

Facelets視圖常常被製作成XHTML頁面,JSF承作支援XHTML頁面一致製作使用XHTML傳統DTD,如所列的在
http://www.w3.org/TR/xhtml1/#a_dtd_XHTML-1.0-Transitional

根據約定,網頁使用XHTML所建立的有著.xhtml的副檔名

標籤庫支援

JSF技術支援不同的標籤庫來增加components到網頁上
為了支援JSF標籤庫結構,Facelets使用XML命名空間宣告

下表為Facelets所支援的標籤庫

標籤庫 統一資源識別(URI) 字首(Prefix) 範例 內容
JSF Facelets標籤庫 http://java.sun.com/jsf/facelets ui: ui:component
ui:insert
模板用標籤
JSF HTML標籤庫 http://java.sun.com/jsf/html h: h:head
h:body
h:outputText
h:inputText
JSF所有UIComponents的components標籤
JSF核心標籤庫 http://java.sun.com/jsf/core f: f:actionListener
f:attribute
給JSF客制動作的標籤,它們在任何特定RenderKit是獨立的
JSTL核心標籤庫 http://java.sun.com/jsp/jstl/core c: c:foreach
c:catch
JSTL 1.1核心標籤
JSTL功能標籤庫 http://java.sun.com/jsp/jstl/functions fn: fn:toUpperCase
fn:toLowerCase
JSTL 1.1功能標籤

除此之外,Facelets也支援組合components標籤,讓你可以宣告客製化字首,更多的資訊以後會提到。

統一表現語言(Unified Expression Language)支援

基於JSF支援被JSP 2.1所定義的EL語法,Facelets使用EL來參考backing beans的屬性和方法,EL可以被使用來連
結component物件或是值到managed-bean方法或是managed-bean屬性,更多的資訊以後會提到。

開發簡單的Facelets應用程式

使用Facelets開發簡單的JSF應用程式需要下列工作:

  • 開發backing beans
  • 製作頁面使用component標籤
  • 定義頁面導向
  • 映射FacesServlet實例
  • 加入managed bean宣告

製作Facelets應用程式

這個範例要做的是猜數字,頁面會要求你猜0~10的數字,並用隨機數字驗證你的輸入,然後使用其他頁面回應你是否正確。

開發Backing Bean

在一個典型的JSF應用程式,每一個在應用程式的頁面都連到一個backing bean,backing bean定義方法和屬性與
components互相相關。

下面的managed bean類別, UserNumberBean.java產生一個0~10之間的隨機數字

package guessNumber;

import java.util.Random;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class UserNumberBean {
    Integer randomInt = null;
    Integer userNumber = null;
    String response = null;
    private long maximum=10;
    private long minimum=0;

    public UserNumberBean() {
        Random randomGR = new Random();
        randomInt = new Integer(randomGR.nextInt(10));
        System.out.println( " Duke’s number: " + randomInt);
    }

    public void setUserNumber(Integer user_number) {
        userNumber = user_number;
    }

    public Integer getUserNumber() {
        return userNumber;
    }

    public String getResponse() {
        if ((userNumber != null) && (userNumber.compareTo(randomInt) == 0))
        {
            return " Yay! You got it! " ;
        }
        else
        {
            return " Sorry, " + userNumber + " is incorrect. " ;
        }
    }

    public long getMaximum() {
        return (this.maximum);
    }

    public void setMaximum(long maximum) {
        this.maximum = maximum;
    }

    public long getMinimum() {
        return (this.minimum);
    }

    public void setMinimum(long minimum) {
        this.minimum = minimum;
    }
}

注意@ManagedBean宣告,這註冊了backing bean為一個JSF承做資源,@SeesionScoped宣告註冊bean scope為
session

製作Facelets視圖

製作頁面或是試圖是頁面撰寫者的責任,這個工作包含加入components到頁面,連接components到backing bean的值
和屬性,以及註冊轉換器和驗證器或是聆聽器到components上。

更多的範例應用程式,XHTML網頁做了前端的服務,第一個範例頁面稱作greeting.xhtml

網頁的第一部份宣告了頁面的內容型態為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 " >
The next section declares the XML namespace for the tag libraries that are used in the web page:
<html xmlns= " http://www.w3.org/1999/xhtml "
xmlns:f= " http://java.sun.com/jsf/core "
xmlns:h= " http://java.sun.com/jsf/html " >
The next section uses various tags to insert components into the web page:
<!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 " >
<h:head>
<title>Facelets Guess Number Application</title>
</h:head>
<h:body>
<h:form>
<h:graphicImage value= " #{resource[’images:wave.med.gif’]} " />
<h2>
Hi,
<p>My name is Duke. I am thinking of a number between <b>
#{userNumberBean.minimum} and #{userNumberBean.maximum}.
</b> Can you guess it ?</p>
<h:inputText
id= " userNo "
value= " #{userNumberBean.userNumber} " >
<f:validateLongRange
minimum= " #{userNumberBean.minimum} "
maximum= " #{userNumberBean.maximum} " />
</h:inputText>
<h:commandButton id= " submit " value= " Submit " action= " response.xhtml " />
<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>
</h:body>
</html>
我已經懶得indent了...請自行indent...

注意到使用Facelets HTML標籤來加入components和Facelets核心標籤來驗證使用者輸入,一個inputText元件
接受使用者輸入和設定backing bean屬性userNumber的值透過EL表示法#{userNumberBean.userNumber},
藉著JSF標準的驗證器f:validateLongRange,輸入值被做範圍驗證。

圖片檔案wave.med.gif被加入為頁面資源,更多細節等等馬上會討論。

submit指令按鈕開始驗證輸入資料,使用暗示導向(implicit navigation),它將client導向其他的頁面回應.xhtml
來回應你的輸入。

你現在可以開始製作回應頁面response.xhtml

<!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 " >
<h:head>
<title>Guess Number Facelets Application</title>
</h:head>
<h:body>
<h:form>
<h:graphicImage value= " #{resource[’images:wave.med.gif’]} " />
<h2>
<h:outputText id= " result " value= " #{userNumberBean.response} " />
</h2>
<h:commandButton id= " back " value= " Back " action= " greeting.xhtml " />
</h:form>
</h:body>
</html>

設定應用程式

設定JSF應用程式需要多種的設定工作,包含加入managed-bean宣告,導向規則和資源連結宣告在應用程式資源文檔裡,
例如說faces-config.xml檔,以及映射Faces Servlet在網頁佈署器文檔例如web.xml,應用程式設定是另外一個
更進階的主題,以後再說:P

如果你使用NetBeans IDE,web佈署器已經自動幫你製作出來了,使用這樣的IDE只要改變default greeting page
原本是index.xhtml為greeting.xhtml即可。這裡是一個web.xml文檔的範例

<?xml version= " 1.0 " encoding= " UTF-8 " ?>
<web-app version= " 3.0 " xmlns= " http://java.sun.com/xml/ns/javaee "
xmlns:xsi= " http://www.w3.org/2001/XMLSchema-instance "
xsi:schemaLocation= " http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd " >
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<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>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/greeting.xhtml</welcome-file>
</welcome-file-list>
</web-app>

注意到PROJECT_STAGE參數的使用,ProjectStage是一個背景參數用來認定JSF應用程式在生命週期的狀態。

應用程式的階段影響應用程式的行為,例如一個計畫階段被定義為Development,除錯訊息會被自動產生給使用者,如果
這個參數沒被定義,預設定義是為Production, ProjectStage有更詳細的定義在更進階的文章(以後吧)

建立、打包、佈署以及執行應用程式

在這章所教導的這個Facelets應用程式範例可以被建立、打包、佈署使用Java EE 6 SDK透過NetBeans IDE。

製作應用程式步驟

  1. 建立guessNumber package
  2. 建立UserNumberBean class到guessNumber package
  3. 建立XHTML頁面 greeting.xhtml 跟 response.xhtml
  4. 編輯XHTML文件和加入Facelets內容到裡面
    1. 加入圖片為應用程式的一部分
    2. 製作一個資料夾命名為resources在存放網頁的資料夾之下
    3. 製作一個子資料夾命名為images在resources之下
    4. 將圖片存到resources/images資料夾
  5. 修改web.xml內的welcome page為greeting.html
  6. 執行

模板(Templating)

JSF提供工具來實做使用者介面,這些工具容易延伸跟重用,模板是一個非常有用的Facelets特色,讓你可以製作可以
行動像一個基地或是模板給其他應用程式頁面的頁面。藉由使用模板,你可以重用程式碼和躲避重新製作相同結構的頁面
模板也幫助維護應用程式大量頁面的標準外觀樣式。

下面的表格列出了被用來做模板的Facelets標籤以及它們各自的功能。

Tag Function
ui:componet 定義一個要被製造及加入到component樹的component
ui:composition 定義一個選擇性地使用模板的頁面composition,內容在這個標籤外的會被忽略
ui:debug 定義一個要被製造和加入到component樹的除錯component
ui:define 定義被插入在模板裡的頁面內容
ui:decorate 與compostition標籤相似但是不忽視在這個標籤外面的內容
ui:fragement 與component標籤相似,但是不忽視在這個標籤外面的內容
ui:include 封裝和重複使用內容在多個頁面
ui:insert 插入內容到一個模板
ui:param 被用來傳入參數到一個被包含的文件裡
ui:repeat 被使用來替代loop標,例如c:forEach或是h:dataTable
ui:remove 卸下頁面的內容

更多的Facelets templating標籤請看PDL在
http://java.sun.com/javaee/javaserverfaces/2.0/docs/pdldocs/facelets/index.html

Facelets標籤庫包含了主要templating標籤,一個template頁面是被製作藉由這個標籤,這個讓你
給一個頁面定義預設架構,一個template頁面可以被重用作為另外一個頁面的template。

下面是一個template範例被存為template.xhtml

<!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 " >
<h:head>
<meta http-equiv= " Content-Type " content= " text/html; charset=UTF-8 " />
<link href= " ./resources/css/default.css " rel= " stylesheet " type= " text/css " />
<link href= " ./resources/css/cssLayout.css " rel= " stylesheet " type= " text/css " />
<title>Facelets Template</title>
</h:head>
<h:body>
<div id= " top " class= " top " >
<ui:insert name= " top " >Top Section</ui:insert>
</div>
<div>
<div id= " left " >
<ui:insert name= " left " >Left Section</ui:insert>
</div>
<div id= " content " class= " left_content " >
<ui:insert name= " content " >Main Content</ui:insert>
</div>
</div>
</h:body>
</html>

範例頁定義一個被分割為三個部份的HTML頁面,上部份,左部份和主要部份,這個部份有一個stylesheets關聯它們,一
樣的架構可以被重用在應用程式內的其他頁面

client頁面呼叫template透過標籤,在下面的範例,一個client頁面命名為templateclient.xhtml
引發template page從先前的template.xhtml,一個client頁面允許內容被插入使用標籤

下面是templateclient.xhtml範例

<!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 " >
<h:body>
<ui:composition template= " ./template.xhtml " >
<ui:define name= " top " >
Welcome to Template Client Page
</ui:define>
<ui:define name= " left " >
<h:outputLabel value= " You are in the Left Section " />
</ui:define>
<ui:define name= " content " >
<h:graphicImage value= " #{resource[’images:wave.med.gif’]} " />
<h:outputText value= " You are in the Main Content Section " />
</ui:define>
</ui:composition>
</h:body>
</html>

你可以使用NetBeans IDE來製作Facelets template和client頁面,更多的製作頁面資訊請參考
http://netbeans.org/kb/docs/web/jsf20-intro.html

Composite Components(組合元件)

JSF使用Facelets提供組合元件的概念,一個組合元件可以被認為是一個作為component的特別型態template

任何component本質上是一個可重複使用特定功能的程式碼片段,舉個例子,一個inputText元件能夠接受使用者的輸入
一個元件也擁有驗證器、轉換器和聆聽器依附與它來展現特定的定義動作。

一個組合元件是一個包含一個標籤集合和其他存在的component的component,這是可以被重用的,使用者製的元件
,能夠被客製化,定義功能也能夠有驗證器,轉換器和聆聽器依附與它,就如同任何其他JSF的component

在Facelets上,任何XHTML頁面被插入使用標籤語言和其他元件,可以被轉換成一個組合元件,使用resources功能
組合元件可以被儲存在一個由應用程式所定義的資源位置庫裡。

下面的表格列出最常被使用的composite標籤和它們的功能

Tag Function
composite:interface 宣告一個使用組合元件的契約,這個組合元件可以被使用為單一元件,組合元件的特色集合是一個特色聯集被宣告在使用契約裡
composite:implementation 定義組合元件的承做,如果一個元素出現,這一定會跟互相呼應
composite:attribute 宣告一個可能會被給予組合元件實例的屬性
compiste:insertChildren 任何子元件或是模板文字文件在組合元件標籤被使用在頁面會被「再父母化」到組合元件裡當這個被指示藉由放置在composite:implementation部份裡
composite:valueHolder
composite:editableValueHolder
composite:actionSource

更多詳細資訊請看

http://java.sun.com/javaee/javaserverfaces/2.0/docs/pdldocs/facelets/index.html

<!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:composite= " http://java.sun.com/jsf/composite "
xmlns:h= " http://java.sun.com/jsf/html " >
<h:head>
<title>This content will not be displayed
</title>
</h:head>
<h:body>
<composite:interface>
<composite:attribute name= " value " required= " false " />
</composite:interface>
<composite:implementation>
<h:outputLabel value= " Email id: " >
</h:outputLabel>
<h:inputText value= " #{cc.attrs.value} " >
</h:inputText>
</composite:implementation>
</h:body>
</html>

注意到使用cc.attrs.value當定義inputText元件的值,cc代表composite component,#{cc.attrs.ATTRIBUTE_NAME}
表示被使用來存取被定義在組合元件的介面的屬性。

先前的範例內容被儲存為email.xhtml,在一個應用程式網頁根目錄資料夾下名為resources/emcomp,這個資料夾被
認為是一個JSF的library,以及一個UIcomponent可以被存取從這個library,更多的關於resources等等會說明

一個網頁使用組合元件通常被稱為using page.這個using page包含一個參考到組合元件,在xml命名空間宣告:

<!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:em= " http://java.sun.com/jsf/composite/emcomp/ " >
<h:head>
<title>Using a sample composite component</title>
</h:head>
<body>
<h:form>
<em:email value= " Enter your email id " />
</h:form>
</body>
</html>

本地組合元件庫被定義在xml命名空間使用宣告
xmlns:em= " http://java.sun.com/jsf/composite/emcomp/ "
元件本身被存取透過使用標籤em:email,這個先前的範例內容可以被儲存為一個網頁命名為emuserpage.xhtml在網頁
根目錄下面,當編譯完成和佈署在server上時,我們可以存取它們使用下面的URL:

http://localhost:8080//faces/emuserpage.xhtml

資源

應用程式需要適當的給予資源在任何的軟體製作,資源包含圖片、腳本檔、和使用者自製元件庫,對於JSF,資源必須被收集
在標準的位置,一定是下列之中的其中之一

  • 一個資源package在網頁應用程式根目錄一定要有子目錄resources資料夾
  • 一個資源package在網頁應用程式的classpath,一定要在META-INF/resources/下一個子資料夾

JSF執行時會從上面這些路徑照順序查找資源

資源識別可以使用下列獨特的符合字串格式:
[localePrefix/][libraryName/][libraryVersion/]resource name[/resourceVersion]

資源識別的元素在brackets([])裡是選擇性的,這只是指出資源名稱是一個被要求的元素,通常是一個文件名稱

資源可以被認為是一個library位置,任何製作品,例如一個組合元件或是模板被儲存在資源資料夾對其他元件而言變成可
存取的,便可以使用它們來製作一個資源實例。

No comments:

Post a Comment