javascript
1.5 Hello, world! 解剖 -JSF实战 -hxzon -jsf学习笔记
為什么80%的碼農都做不了架構師?>>> ??
1.5 Hello, world! 解剖 -JSF實戰 -hxzon -jsf學習筆記
既然已經對JSF能夠解決什么問題有了初步理解,我們來開始開發一個簡單的應用。本節假定你已熟悉Java Web應用和JSP(關于這些技術的信息,參考1.2節)。下面來解剖一個簡單的基于HTML的Web應用,該應用有兩個頁面:hello.jsp 和 goodbye.jsp。
hello.jsp頁面做以下工作:
l??? 顯示文本“Welcome to JSF!”;
l??? 有一個表單,其中有個文本框,要求輸入1 到 500 的整數;
l??? 在名為numControls 的JavaBean 屬性中存儲提交的文本值;
l??? 文本框下面有個表格;
l??? 有一個標簽為Redisplay的按鈕,點擊它時,將添加一個numControls 輸出UI組件到表格中(清除先前已經有了的UI組件);
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?!闭缒闼?#xff0c;此消息是由注冊到頁面中的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
|
與其他很多框架不同,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 配置的某些方面,特別是導航,可以使用工具進行可視化處理?,F在,來看看應用程序在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?
轉載于:https://my.oschina.net/hxzon/blog/99
總結
以上是生活随笔為你收集整理的1.5 Hello, world! 解剖 -JSF实战 -hxzon -jsf学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深证指数
- 下一篇: windows常见的运行命令以及各快捷键