1.5 Hello, world! 解剖 -JSF實戰 -hxzon -jsf學習筆記

1.5 Hello, world! 解剖 -JSF實戰 -hxzon -jsf學習筆記html

既然已經對JSF可以解決什麼問題有了初步理解,咱們來開始開發一個簡單的應用。本節假定你已熟悉Java Web應用和JSP(關於這些技術的信息,參考1.2節)。下面來解剖一個簡單的基於HTML的Web應用,該應用有兩個頁面:hello.jsp 和 goodbye.jsp。java

hello.jsp頁面作如下工做:web

l    顯示文本「Welcome to JSF!」;瀏覽器

l    有一個表單,其中有個文本框,要求輸入1 到 500 的整數;服務器

l    在名爲numControls 的JavaBean 屬性中存儲提交的文本值;框架

l    文本框下面有個表格;jsp

l    有一個標籤爲Redisplay的按鈕,點擊它時,將添加一個numControls 輸出UI組件到表格中(清除先前已經有了的UI組件);ide

l    有一個標籤爲Goodbye的按鈕,點擊它將顯示goodbye.jsp 頁面。工具

goodbye.jsp 頁面作如下工做:學習

l    顯示文本「Goodbye!」;

l    顯示JavaBean 屬性numControls的值。

JSF執行Hello, world!應用程序的大部分工做,可是除了JSP 頁面以外,還有一些其餘要求:

l    HelloBean後臺bean類;

l    Faces配置文件;

l    正確配置的部署描述符。

某些工具能夠簡化部分或者所有需求的建立工做,但在本節,咱們將詳細討論這些原始文件。

在涉足細節以前,先看看Hello, world!在Web瀏覽器中怎樣顯示。應用以hello.jsp開始,如圖1-7所示。頁面中的文本框與HelloBean類中的一個JavaBean屬性相關聯;當用戶在此文本框中輸入一個值,屬性將自動更新(若是值有效)。

圖1-7 數據提交以前的Hello, world!應用程序

若是在文本框中輸入數字64,點擊Redisplay 按鈕,頁面將從新顯示,如圖1-8,共有64個UI輸出組件顯示在表格中。若是清除文本框,而後點擊Redisplay按鈕,將會獲得一個驗證錯誤,如圖1-9所示。若是輸入數字99999,而後點擊Redisplay按鈕,也會獲得驗證錯誤,如圖1-10。

圖1-8 輸入「64」而且點擊Redisplay按鈕後的Hello,world!應用程序。表格內組裝了64個UI輸出組件

圖1-9 對必須填寫的字段提交空值,而且點擊Redisplay按鈕後的Hello,world!應用程序。由於發生了驗證錯誤,相關JavaBean屬性的值未被修改

不要擔憂錯誤信息,你徹底能夠在本身的應用中定製它們。重點在於,在這兩種狀況下,表單提交時,相關的 JavaBean屬性未被修改。

若是點擊Goodbye 按鈕,你將看到goodbye.jsp頁面,如圖1-11。雖然這是徹底不一樣的頁面,JavaBean 屬性的值也會顯示。JSF組件能夠引用應用做用域中的JavaBean。

Hello, world! 示例是一個標準的Java Web應用,它使用標準的Servlet API(雖然它要求標準的Faces 庫)。這五個圖都是由兩個JSP產生的。接下來詳細討論一下。

1.5.1 解剖hello.jsp

主頁面hello.jsp提供了圖1-7~圖1-10的界面。JSF 經過使用定製標籤庫與JSP集成。JSF 定製標籤容許JSP使用Faces UI組件。某些工具使你能夠經過從面板拖放JSF組件來設計JSP頁面。事實上,圖1-1~圖1-3就是在不一樣的IDE中設計hello.jsp 的屏幕截圖。這些IDE最終都產生與代碼清單1-1相似的代碼(固然,也能夠手工編寫JSF頁面)。

圖1-10 在文本框內輸入"99999",而後點擊Redisplay後的Hello, world!應用程序。字段僅接受1~500之間的數值,因此產生如圖所示的驗證錯誤。由於發生了驗證錯誤,相關的JavaBean屬性的值未被修改

圖1-11 點擊Goodbye按鈕後的Hello, world!應用程序。注意JavaBean 屬性,它與第一個頁面中的文本字段保持同步,也顯示在此頁面中

代碼清單1-1 hello.jsp: Hello,world! 應用程序的起始頁面(瀏覽器輸出如圖1-7~圖1-10所示)

首先,導入核心JSF標籤庫。該庫提供諸如驗證和事件處理之類的基本任務的定製標籤。接着,導入基本HTML標籤庫,它提供諸如文本框、輸出標籤和表單之類的UI組件(前綴f和h是建議的,非必要)。

<f:view>標籤必須將全部其餘Faces相關的標籤包圍起來(包括來自於核心標籤和基本HTML標籤庫中的標籤)。

<h:form>標籤表示HtmlForm組件,它是其餘組件的容器,並將信息提交給服務器。在一個頁面內能夠有多個HtmlForm,但輸入組件必須嵌入<h:form>標籤中。

<h:outputText>標籤建立HtmlOutputText 組件,該組件只是在屏幕上顯示只讀數據。此標籤有一個id屬性和一個value 屬性。id 屬性對每一個組件是可選的,不是必需屬性,除非你想要在其餘地方引用該組件(組件可使用客戶端技術(如JavaScript)引用或者在Java 代碼中引用)。Value屬性的值是須要顯示的文本。

<h:message>標籤表示HtmlMessage 組件,它顯示特定組件的驗證和轉換錯誤信息。for 屬性告訴它須要顯示針對標識符爲helloInput的組件的錯誤信息。helloInput是頁面中*處的文本框的標識符。若是沒有錯誤則什麼都不顯示。

<h:outputLabel>標籤建立新的HtmlOutputLabel組件,它用做輸入控件的標註。for屬性將它與該輸入控件相聯繫,即 helloInput 文本框。HtmlOutputLabel不顯示內容,因此還須要下屬HtmlOutputText(由嵌套的<h:outputText> 標籤建立)來顯示標註的文本。

* <h:inputText>標籤用於建立HtmlInputText 組件,該組件接收用戶的文本輸入。注意,該組件的value 屬性是"#{helloBean.numControls}",這是JSF表達式語言(EL)寫成的表達式,引用了後臺bean中的numControls 屬性,該bean名爲HelloBean(JSF EL 基於JSP 2.0引入的表達式語言)。

Faces將自動在不一樣的上下文(請求、會話、應用)中查詢特定的後臺bean。這樣,它將在應用會話中找到在關鍵字helloBean下保存的後臺bean。組件的value屬性和helloBean的numControls 屬性是同步的,其中一個變化了,另外一個也要修改(除非HtmlInputText 組件中的文本無效)。

輸入組件有個required 屬性,它決定該字段是否必須有一個值。這樣,若是required 屬性被設置爲true,則組件只能接受非空輸入。若是用戶輸入空值,頁面將從新顯示,而HtmlMessage()將顯示錯誤信息,如圖1-9所示。

JSF也支持驗證器,它負責確保用戶的輸入是可接受的值。每一個輸入控件均可以與一個或者多個驗證器相關聯。<f:validateLongRange>標籤註冊LongRange驗證器到HtmlInputText 組件。驗證器檢查輸入值以確保用戶輸入是在預設的0~500之間的一個數(包含端點)。若是用戶輸入一個超出此範圍的值,驗證器將拒絕該輸入,頁面從新顯示,而且HtmlMessage()組件顯示錯誤信息,如圖1-10所示。

當用戶輸入被拒絕時,HtmlInputText組件引用的對象的value 屬性不會更新。

HtmlPanelGrid 組件用<h:panelGrid> 標籤來表示。HtmlPanelGrid表現爲其餘組件的可配置容器,將顯示爲HTML表格。

許多JSF 組件均可以經過其JSP標籤的binding屬性直接與後臺bean相聯繫(某些工具可以自動使頁面上的全部組件與後臺bean相聯繫)。此標籤的binding屬性被設置爲"#{helloBean.controlPanel}"。這也是JSF EL表達式,它引用了helloBean的controlPanel屬性,這是HtmlPanelGrid類型的屬性。這樣確保helloBean 老是可以訪問頁面上的HtmlPanelGrid 組件。

<h:commandButton>表示HtmlCommandButton 組件,它顯示爲HTML表單按鈕。HtmlCommandButton在被用戶點擊後會發送動做事件(Action Event)到服務器中的應用。可經過actionListener屬性直接引用事件監聽器(執行事件響應的方法)。第一個HtmlCommandButton的actionListener屬性設置爲"#{helloBean.addControls}"。這還是JSF EL表達式,它告訴JSF去查找helloBean 對象,而後調用其addControls 方法來處理事件。一旦方法執行完畢,頁面將從新顯示。

第2個HtmlCommandButton按鈕設置action屬性而不是actionListener屬性。該屬性的值爲"#{helloBean.goodbye}",這個表達式引用一個特定的處理導航的事件監聽器。這也是爲何點擊這個按鈕將顯示goodbye.jsp頁面,而不是從新顯示hello.jsp頁面的緣由。這個按鈕還有個immediate 屬性設置爲true,這告訴JSF在驗證和更新發生前就執行相關的監聽器。這樣,即便輸入不正確,點擊此按鈕也能夠工做。這就是整個hello.jsp。

代碼清單1-2列出了驗證出錯後的HTML輸出(瀏覽器的視圖顯示效果示於圖1-10)。

代碼清單1-2 hello.jsp的HTML輸出(此代碼是圖1-10的源代碼)

你能夠看到,在JSP中定義的每個組件都在HTML頁面中有一個對應的顯示。注意,<h:form>標籤(),它表示HtmlForm組件,有一個action屬性,它指向調用此頁面的JSP,可是有一個前綴faces。這是Faces servlet的一個別名,是在應用的部署描述符中定義的。從新顯示調用頁面是默認行爲,但Faces應用也能夠導航到其餘頁面(這發生在用戶點擊Goodbye按鈕後)。

HtmlMessage組件()的輸出是文本「Validation Error: Specified attribute is not between the expected values of 1 and 500。」正如你所想,此消息是由註冊到頁面中的LongRange 驗證器產生的。當驗證器拒絕提交輸入不正確值的嘗試時,它也產生錯誤信息,而框架則避免更新相關的JavaBean的屬性值。

對應於JSF組件的每一個HTML元素都有個繼承自JSP中指定的id值的id屬性(若是沒有指定,將自動建立一個)。這就是客戶端標識符(client identifier),它是JSF用來將輸入值映射到服務器組件的標識。某些組件也使用name屬性做爲客戶端標識符。

HtmlPanelGrid組件()的輸出是HTML表格。注意,JSP中的border 和cellspacing 屬性直接傳遞到HTML(大多數標準HTML組件都會暴露一些直接傳遞到瀏覽器的HTML特定屬性)。表格中的每一個單元格都輸出一個HtmlOutputText組件,它是經過Java代碼在響應用戶點擊Redisplay按鈕後添加到其中的(在實際的HTML中,有64 個單元格,由於這是用戶在文本框中輸入的數字。咱們省略了部分代碼,不然將會浪費大量的篇幅!)。

咱們很快就會研究Java代碼,但如今先來看看goodbye.jsp。

1.5.2 解剖goodbye.jsp

goodbye.jsp頁面的效果如圖1-11所示,用戶點擊Goodbye按鈕後顯示。頁面代碼(代碼清單1-3)包含了一些與hello.jsp 頁面中的組件相同的組件:導入JSF標籤庫、一個HtmlForm組件、HtmlOutputText組件。其中一個HtmlOutputText組件引用與前一個頁面中相同的helloBean 對象。這運行得很好,由於對象在應用的會話中,能夠在頁面請求間存活。

代碼清單1-3 goodbye.jsp: Hello, world!應用程序的結束頁面(瀏覽器輸出示於圖1-11)

此頁面產生的HTML和前一節相比無特別須要說明之處,所以就再也不浪費時間。重要的是能夠建立有功能的應用了,包括驗證和導航,儘管僅有兩個頁面(若是不打算展現導航,第一個頁面就已足夠了)。

如今,咱們來看頁面背後的代碼。

1.5.3 檢視HelloBean

hello.jsp和goodbye.jsp都包含了經過JSF EL表達式引用名爲helloBean的後臺bean的JSF組件。這個JavaBean包含了此應用所需的全部內容:兩個屬性和兩個方法。其代碼如代碼清單1-4所示。

代碼清單1-4 HelloBean.java: Hello, world!應用程序的簡單後臺bean

被Goodbye HtmlCommandButton執行

與其餘不少框架不一樣,JSF後臺bean並非非要繼承自特定的類。它們只須要簡單地遵循普通的JavaBean約定,在事件處理方法中使用特定的方法簽名暴露其屬性便可。

numControls屬性被hello.jsp的HtmlInputText組件和goodbye.jsp中的HtmlOutputText組件所引用。不管什麼時候用戶改變 HtmlInputText 組件的值,此屬性的值都要相應改變(若是輸入有效)。

controlPanel屬性的類型是HtmlPanelGrid,後者是在hello.jsp中使用<h:panelGrid>標籤建立的實際的Java類。該標籤的binding屬性與由controlPanel屬性的標籤建立的組件相關。這樣使HelloBean可以操做實際的代碼,即在處執行的任務。

addControls是用來處理action 事件的方法(即動做監聽器方法);你能辨別,由於它接受ActionEvent做爲其惟一的參數。在hello.jsp中,Redisplay按鈕HtmlCommandButton經過其actionListener屬性引用這個方法。這就告訴JSF,在處理用戶點擊Redisplay按鈕時產生的動做事件時,調用這個方法(若是你習慣使用Swing之類的框架,將組件和事件監聽器相聯繫會顯得有些奇怪,由於它們一般須要一個單獨的事件監聽器接口。JSF也支持接口風格的監聽器,可是最好的方法仍是使用監聽器方法,由於它緩解了後臺bean中對適配器類的需求)。

此方法被執行時,它添加新的HtmlOutputText組件到controlPanel中,並執行numControls次(首先清零)。因此,若是numControls的值是64,如例中所述,代碼將建立並添加64個HtmlOutputText實例到controlPanel中。每一個實例的值被設置爲其順序號,從0開始直到63。最後,每一個實例的style屬性都設置爲"color: blue"。

controlPanel是HtmlPanelGrid 實例,它將在HTML表格中顯示其全部的子控件,每一個HtmlOutputText 組件將在一個單獨的表格單元中顯示。圖1-8顯示方法執行後controlPanel的樣子。

與addControls方法相似,goodbye方法也是事件監聽器。然而,它與JSF的導航系統相關聯,因此其職責是返回一個字符串,或者是一個邏輯結果,因而導航系統使用這個結果來決定下一步將載入哪一個頁面。這種類型的方法稱爲動做方法(action method)。hxzon:方法無參數,返回一個字符串,決定導航,對應action屬性。而以前addControls帶有一個ActionEvent參數,無返回值,處理事件。對應actionListener屬性。

goodbye方法經過hello.jsp中的「Goodbye」按鈕HtmlCommandButton的action屬性與該按鈕相關聯。因此用戶點擊Goodbye按鈕時,goodbye方法被執行。在這裏,goodbye 並不執行決定邏輯結果的工做,它只是直接返回"success"。這一結果在Faces 配置文件中與特定的頁面相關聯,咱們將在下面說起。

由於goodbye方法不執行任何處理( 在實際應用中也可能如此),咱們能夠在按鈕的action屬性中經過硬編碼"success"來達到一樣的效果。這是由於導航系統可使用HtmlCommandButton的action屬性,也可使用action 方法的結果(若是該屬性引用了動做方法)。

1.5.4 經過faces-config.xml進行配置

相似於大部分框架,Faces 也有一個配置文件;它名爲faces-config.xml(技術上說,JSF支持多個配置文件,可是如今先保持簡化)。這一配置文件容許你定義導航規則、初始化JavaBean、註冊本身的JSF組件和驗證器(validator)以及配置JSF應用的其餘部分。這裏的簡單應用只需配置bean初始化和導航。具體的配置文件如代碼清單1-5所示。

代碼清單1-5 faces-config.xml : Hello world! 應用程序的Faces配置

首先,JSF配置文件是XML文檔,根節點是<faces-config>()。

在此文件中,能夠聲明一個或者多個在應用中使用的JavaBean。能夠給它們分別設置一個名字(該名稱可經過JSF EL表達式引用)、一個說明、一個範圍,甚至能夠初始化它們的屬性。在配置文件中聲明的對象稱爲受管bean(managed bean)。在代碼清單中,咱們聲明瞭在整個Hello, world!應用程序中使用的helloBean對象()。請注意,對象的名稱是"helloBean",這與在兩個JSP中的JSF EL表達式中使用的名稱是同樣的。其實現類是org.jia.hello.HelloBean,這是在前一節所講的後臺bean類的名稱。受管bean 的名稱和對象的類名稱不必定相同。

聲明導航和聲明受管bean同樣簡單。每一個JSF 應用能夠有一個或者多個導航規則。一個導航規則定義了從特定頁面出發的可能路由。每種路由稱爲一個導航案例(navigation case)。配置文件清單顯示了Hello, world!應用程序的hello.jsp頁面的導航規則()。hello.jsp有個Goodbye 按鈕,該按鈕用於載入另外一個頁面,因此這裏只有一個單一導航案例:若是結果是"success",則顯示goodbye.jsp。這個結果是由helloBean的 goodbye 方法返回的,該方法在用戶單擊Goodbye按鈕時被執行。

值得指出的是JSF 配置的某些方面,特別是導航,可使用工具進行可視化處理。如今,來看看應用程序在Web應用的層面是如何配置的。

1.5.5 配置web.xml

全部的J2EE Web應用都經過web.xml 部署描述符來進行配置,Faces應用也不例外。然而,JSF 應用要求你必須指定FacesServlet,而這一般是應用的主servlet。另外,請求必須被映射到這個servlet。咱們的Hello, world!應用程序的部署描述符如代碼清單1-6所示。你可使用一些工具來產生Faces應用所須要的元素。

代碼清單1-6 web.xml:Hello world!應用程序的部署描述符

到此,咱們剖析完了Hello world!。你能夠看到,JSF作了大部分的工做——驗證、事件處理、導航及UI組件管理等等。隨着更加深刻地探討JSF的各個方面,你將得到對其所提供的各類服務的更深的理解,從而能夠將它應用在你的應用程序中,而避免一些使人抱怨的繁瑣工做。

hxzon:faces-config.xml中,配置託管bean,導航規則。託管bean既是model也是action。
導航規則from-view-id表示觸發的頁面,from-outcome表示前進頁面的邏輯名(由導航方法返回),to-view-id表示前進的頁面位置。一個managed-bean配置一個託管bean,一個navigation-rule配置一個頁面的導航規則(前進規則)。

http://hi.baidu.com/hxzon/blog/item/498cc9fc33ee878ab801a0c8.html 

相關文章
相關標籤/搜索