JSF應(yīng)用程序的生命周期
與很多流行的觀點不同,我們無需了解技術(shù)工作原理的所有細(xì)節(jié),就可以編寫 JSF 應(yīng)用程序。您只需要給自己設(shè)置一個項目,并從頭到尾不斷修修補補,這樣就可以學(xué)習(xí)到大量的知識。另一方面,理解必要的基礎(chǔ)知識可以使您的開發(fā)工作更加有效 —— 而且會節(jié)省很多時間。
在本系列 懷疑論者的 JSF 的第 2 篇文章中,我們將逐一介紹一下 JSF 請求處理生命周期的 5 個階段。我們將介紹在每個階段中會發(fā)生什么,以及這些階段是如何相互連接在一起的,然后使用一個示例程序來展示實際的生命周期。我們還將向您介紹如何在 JSF 開發(fā)中采用 Struts Tiles,以及如何組合使用 JSF 和 JavaScript 技術(shù)進行即時事件的處理。
正如上一篇文章中介紹的一樣,示例程序的默認(rèn)編譯環(huán)境是 Maven。您可以通過點擊頁面頂部或底部的 Code 圖標(biāo)下載源代碼。為了簡單性起見,您會發(fā)現(xiàn)與上一篇文章中一樣的示例設(shè)置。
JSF應(yīng)用程序的生命周期:概述
JSF 程序生命周期的 5 個階段如下(注意每個階段的事件處理):
1. 恢復(fù)視圖
2. 應(yīng)用請求的值;處理驗證
3. 更新模型值;處理事件
4. 調(diào)用程序;處理事件
5. 進行響應(yīng);處理事件
這 5 個階段顯示了 JSF 通常處理 GUI 的順序。雖然這個清單列出了每個階段中事件處理的可能執(zhí)行順序,但是 JSF生命周期很難是固定一成不變的。您可以通過忽略某個階段或合并整個生命周期從而對執(zhí)行順序進行修改。例如,如果一個無效的請求值被拷貝到一個組件中,那么當(dāng)前的視圖就會重新顯示,而有些階段就可能不會執(zhí)行。在這種情況中,您可以執(zhí)行一個 FacesContext.responseComplete 方法調(diào)用,將用戶重定向到一個不同的頁面上,然后使用請求分發(fā)器(從 FacesContext 中的請求對象中獲得)將其轉(zhuǎn)發(fā)到一個適當(dāng)?shù)?Web 資源上。另外,您可以調(diào)用 FacesContext.renderResponse 重新顯示原來的視圖。(詳細(xì)信息請參看下面的示例程序。)
關(guān)鍵是讓生命周期構(gòu)成您的開發(fā)項目,而不完全依賴于生命周期。在需要時,您可以修改生命周期,而不用擔(dān)心破壞您的程序。在大部分情況中,您會發(fā)現(xiàn) JSF生命周期是值得遵守的,因為它的邏輯非常好。表單必須在任何應(yīng)用程序邏輯執(zhí)行之前進行驗證,并且在進行驗證之前,必須對域中的數(shù)據(jù)進行轉(zhuǎn)換。遵守生命周期的規(guī)定,可以讓您更自由地考慮有關(guān)驗證和轉(zhuǎn)換的問題,而不是請求處理本身的階段。有一點非常重要:其他 Web 框架也都具有類似的生命周期;它們只不過是沒有很好地進行宣傳。
專注
有些使用 JSF 的開發(fā)者可能從來都不會編寫一個組件,也不會對框架進行任何擴展;而另外一些人則專注于這種任務(wù)的開發(fā)。盡管 JSF生命周期與大部分那其他項目都是相同的,但是根據(jù)在項目中的角色您可以采用不同的階段。如果您更專注于通用的應(yīng)用程序開發(fā),就可能會關(guān)注請求處理生命周期的中間階段:
◆應(yīng)用請求值
◆更新模型值
◆調(diào)用程序
如果您專注于 JSF 組件的開發(fā),就可能會關(guān)注于整個生命周期中的第一個階段和最后一個階段:
◆恢復(fù)視圖
◆進行響應(yīng)
在接下來的幾節(jié)中,我們將遍歷 JSF 請求處理生命周期的每個步驟,包括事件處理和驗證。了解了每個步驟的基本知識之后,我們將簡要介紹一個示例程序,它可以展示這些步驟如何一起使用。在開始之前,首先來看一下圖 1,這是一個有關(guān) JSF生命周期的圖。
階段 1:恢復(fù)視圖
在 JSF生命周期的第一個階段 ——恢復(fù)視圖 —— 中,會有一個來自 FacesServlet 控制器的請求。控制器會對請求進行考查,并提取出視圖的 ID,這是由 JSP 頁面的名字來確定的。
JSF 框架控制器使用這個視圖 ID 來為當(dāng)前的視圖查找組件。如果這個視圖尚未存在,那么 JSF 控制器就會創(chuàng)建它。如果這個視圖早已存在,那么 JSF 控制器就會使用它。這個視圖包含了所有的 GUI 組件。
生命周期的這個階段表示為三個視圖實例:新視圖、原始視圖和后視圖,每個視圖的處理方式都不相同。在 新視圖 的情況中,JSF 會構(gòu)建 Faces 頁面的視圖,并將事件處理程序和驗證程序綁定到組件上。這個視圖被保存在一個 FacesContext 對象中。
FacesContext 對象包含了 JSF 用來管理當(dāng)前會話中當(dāng)前請求的 GUI 組件狀態(tài)所需要的所有狀態(tài)信息。FacesContext 將視圖保存在自己的 viewRoot 屬性中;viewRoot 包含了當(dāng)前視圖 ID 的所有 JSF 組件。
在 原始視圖 的情況中(第一次加載的是一個頁面),JSF 會創(chuàng)建一個空視圖。這個空視圖會在用戶事件產(chǎn)生時進行填充。JSF 可以直接從原始視圖過渡到進行響應(yīng)的階段。
在 后視圖(postback) 的情況中(用戶返回之前訪問過的頁面),包含頁面的視圖早已經(jīng)存在了,因此只需要進行恢復(fù)就可以了。在這種情況中,JSF 就使用現(xiàn)有視圖的狀態(tài)信息來重構(gòu)狀態(tài)。后視圖的下一個階段是應(yīng)用請求值。
階段 2:應(yīng)用請求值
應(yīng)用請求值 階段的目的是讓每個組件檢索自己當(dāng)前的狀態(tài)信息。這些組件必須首先通過 FacesContext 對象進行檢索或創(chuàng)建(使用其值)。雖然組件值也可以從 cookie 或頭文件中進行檢索,但是它們通常是通過請求參數(shù)進行檢索的。
如果一個組件的即時事件處理屬性 沒有 設(shè)置為 true,那么就會對這些值進行轉(zhuǎn)換。因此,如果 域 被綁定到一個 Integer 屬性上,那么該值就會被轉(zhuǎn)換為一個 Integer 類型。如果值的轉(zhuǎn)換失敗了,那么就會生成一個錯誤消息,并在 FacesContext 中進行排隊,在產(chǎn)生響應(yīng)的階段會顯示其中的消息,同時還會顯示所有的驗證錯誤。
如果一個組件的即時事件處理屬性 的確 被設(shè)置為 true,那么這些值就會被轉(zhuǎn)換為適當(dāng)?shù)念愋停⑦M行有效性驗證。然后轉(zhuǎn)換后的值會被保存到組件中。如果值轉(zhuǎn)換或值的有效性驗證失敗了,就會生成一個錯誤消息,并在 FacesContext 中進行排隊,在產(chǎn)生響應(yīng)的階段會顯示其中的消息,同時還會顯示所有的驗證錯誤。
處理驗證
生命周期中的第一個事件處理發(fā)生在應(yīng)用請求值階段之后。在這個階段中,每個組件都有一些值需要根據(jù)應(yīng)用程序的驗證規(guī)則進行有效性驗證。這些驗證規(guī)則可以是預(yù)先進行定義的(JSF 中提供的),也可以由開發(fā)者進行定義。用戶所輸入的值會與這些驗證規(guī)則進行比較。如果說輸入的值無效,就會向 FacesContext 中添加一個錯誤消息,并且該組件會被表示為無效的。如果一個組件被表示為無效的,那么 JSF 就會轉(zhuǎn)到產(chǎn)生響應(yīng)的階段,在這個階段中會顯示當(dāng)前的視圖,以及驗證錯誤消息。如果沒有有效性驗證錯誤,那么 JSF 就會轉(zhuǎn)到更新模型值的階段。
階段 3:更新模型值
JSF 應(yīng)用程序生命周期中的第三個階段 ——更新模型值 —— 負(fù)責(zé)更新服務(wù)器端模型的實際值,通常來講,這都是通過更新后臺 bean(稱為管理 bean)的屬性實現(xiàn)的。只有那些與組件值綁定在一起的 bean 屬性才會被更新。注意這個階段發(fā)生在有效性驗證之后,因此可以確保拷貝到 bean 屬性的值都是有效的(至少在表單域一級都是有效的;在業(yè)務(wù)規(guī)則一級仍可能無效)。
階段 4:調(diào)用程序
在生命周期的第四個階段 ——調(diào)用程序 —— 中,JSF 控制程序會調(diào)用程序來處理 表單 的提交操作。組件值已經(jīng)經(jīng)過了類型轉(zhuǎn)換和有效性驗證,并被應(yīng)用到模型對象中了,因此您現(xiàn)在可以使用它們來執(zhí)行應(yīng)用程序的業(yè)務(wù)邏輯了。
在這個階段,您還可以為一個給定的序列或很多可能的序列指定后面的邏輯視圖,這可以通過為一次成功的表單提交定義一個特定的結(jié)果并返回這個結(jié)果來實現(xiàn)。例如:在成功輸出時,將用戶重定向到下一頁中。要讓這種導(dǎo)航工作能夠起作用,您需要在 faces-config.xml 文件中創(chuàng)建一個到 成功輸出 的映射作為一條導(dǎo)航規(guī)則。一旦導(dǎo)航發(fā)生之后,您就轉(zhuǎn)換到生命周期的最后一個階段了。
階段 5:進行響應(yīng)
在生命周期的第五個階段 ——進行響應(yīng) —— 中,您可以在視圖中顯示當(dāng)前狀態(tài)中的所有組件。
【編輯推薦】