欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JSF 應用程序的生命周期

JSF 生命周期:概述
JSF 程序生命周期的 5 個(gè)階段如下(注意每個(gè)階段的事件處理):

  1. 恢復視圖
  2. 應用請求的值;處理驗證
  3. 更新模型值;處理事件
  4. 調用程序;處理事件
  5. 進(jìn)行響應;處理事件

這 5 個(gè)階段顯示了 JSF 通常處理 GUIi 的順序。雖然這個(gè)清單列出了每個(gè)階段中事件處理的可能執行順序,但是 JSF 的生命周期很難是固定一成不變的。您可以通過(guò)忽略某個(gè)階段或合并整個(gè)生命周期從而對執行順序進(jìn)行修改。例如,如果一個(gè)無(wú)效的請求值被拷貝到一個(gè)組件中,那么當前的視圖就會(huì )重新顯示,而有些階段就可能不會(huì )執行。在這種情況中,您可以執行一個(gè) FacesContext.responseComplete 方法調用,將用戶(hù)重定向到一個(gè)不同的頁(yè)面上,然后使用請求分發(fā)器(從 FacesContext 中的請求對象中獲得)將其轉發(fā)到一個(gè)適當的 Web 資源上。另外,您可以調用 FacesContext.renderResponse 重新顯示原來(lái)的視圖。(詳細信息請參看下面的示例程序。)

關(guān)鍵是讓生命周期構成您的開(kāi)發(fā)項目,而不完全依賴(lài)于生命周期。在需要時(shí),您可以修改生命周期,而不用擔心破壞您的程序。在大部分情況中,您會(huì )發(fā)現 JSF 的生命周期是值得遵守的,因為它的邏輯非常好。表單必須在任何應用程序邏輯執行之前進(jìn)行驗證,并且在進(jìn)行驗證之前,必須對域中的數據進(jìn)行轉換。遵守生命周期的規定,可以讓您更自由地考慮有關(guān)驗證和轉換的問(wèn)題,而不是請求處理本身的階段。有一點(diǎn)非常重要:其他 Web 框架也都具有類(lèi)似的生命周期;它們只不過(guò)是沒(méi)有很好地進(jìn)行宣傳。

專(zhuān)注
有些使用 JSF 的開(kāi)發(fā)者可能從來(lái)都不會(huì )編寫(xiě)一個(gè)組件,也不會(huì )對框架進(jìn)行任何擴展;而另外一些人則專(zhuān)注于這種任務(wù)的開(kāi)發(fā)。盡管 JSF 的生命周期與大部分那其他項目都是相同的,但是根據在項目中的角色您可以采用不同的階段。如果您更專(zhuān)注于通用的應用程序開(kāi)發(fā),就可能會(huì )關(guān)注請求處理生命周期的中間階段:

  • 應用請求值
  • 更新模型值
  • 調用程序

如果您專(zhuān)注于 JSF 組件的開(kāi)發(fā),就可能會(huì )關(guān)注于整個(gè)生命周期中的第一個(gè)階段和最后一個(gè)階段:

  • 恢復視圖
  • 進(jìn)行響應

在接下來(lái)的幾節中,我們將遍歷 JSF 請求處理生命周期的每個(gè)步驟,包括事件處理和驗證。了解了每個(gè)步驟的基本知識之后,我們將簡(jiǎn)要介紹一個(gè)示例程序,它可以展示這些步驟如何一起使用。在開(kāi)始之前,首先來(lái)看一下圖 1,這是一個(gè)有關(guān) JSF 生命周期的圖。

圖 1. JSF 生命周期

階段 1:恢復視圖
在 JSF 生命周期的第一個(gè)階段 ——恢復視圖 —— 中,會(huì )有一個(gè)來(lái)自 FacesServlet 控制器的請求??刂破鲿?huì )對請求進(jìn)行考查,并提取出視圖的 ID,這是由 JSPi 頁(yè)面的名字來(lái)確定的。

JSF 框架控制器使用這個(gè)視圖 ID 來(lái)為當前的視圖查找組件。如果這個(gè)視圖尚未存在,那么 JSF 控制器就會(huì )創(chuàng )建它。如果這個(gè)視圖早已存在,那么 JSF 控制器就會(huì )使用它。這個(gè)視圖包含了所有的 GUI 組件。

生命周期的這個(gè)階段表示為三個(gè)視圖實(shí)例:新視圖、原始視圖和后視圖,每個(gè)視圖的處理方式都不相同。在 新視圖 的情況中,JSF 會(huì )構建 Faces 頁(yè)面的視圖,并將事件處理程序和驗證程序綁定到組件上。這個(gè)視圖被保存在一個(gè) FacesContext 對象中。

FacesContext 對象包含了 JSF 用來(lái)管理當前會(huì )話(huà)中當前請求的 GUI 組件狀態(tài)所需要的所有狀態(tài)信息。FacesContext 將視圖保存在自己的 viewRoot 屬性中;viewRoot 包含了當前視圖 ID 的所有 JSF 組件。

原始視圖 的情況中(第一次加載的是一個(gè)頁(yè)面),JSF 會(huì )創(chuàng )建一個(gè)空視圖。這個(gè)空視圖會(huì )在用戶(hù)事件產(chǎn)生時(shí)進(jìn)行填充。JSF 可以直接從原始視圖過(guò)渡到進(jìn)行響應的階段。

后視圖(postback) 的情況中(用戶(hù)返回之前訪(fǎng)問(wèn)過(guò)的頁(yè)面),包含頁(yè)面的視圖早已經(jīng)存在了,因此只需要進(jìn)行恢復就可以了。在這種情況中,JSF 就使用現有視圖的狀態(tài)信息來(lái)重構狀態(tài)。后視圖的下一個(gè)階段是應用請求值。

階段 2:應用請求值
應用請求值 階段的目的是讓每個(gè)組件檢索自己當前的狀態(tài)信息。這些組件必須首先通過(guò) FacesContext 對象進(jìn)行檢索或創(chuàng )建(使用其值)。雖然組件值也可以從 cookie 或頭文件中進(jìn)行檢索,但是它們通常是通過(guò)請求參數進(jìn)行檢索的。

如果一個(gè)組件的即時(shí)事件處理屬性 沒(méi)有 設置為 true,那么就會(huì )對這些值進(jìn)行轉換。因此,如果 被綁定到一個(gè) Integer 屬性上,那么該值就會(huì )被轉換為一個(gè) Integer 類(lèi)型。如果值的轉換失敗了,那么就會(huì )生成一個(gè)錯誤消息,并在 FacesContext 中進(jìn)行排隊,在產(chǎn)生響應的階段會(huì )顯示其中的消息,同時(shí)還會(huì )顯示所有的驗證錯誤。

如果一個(gè)組件的即時(shí)事件處理屬性 的確 被設置為 true,那么這些值就會(huì )被轉換為適當的類(lèi)型,并進(jìn)行有效性驗證。然后轉換后的值會(huì )被保存到組件中。如果值轉換或值的有效性驗證失敗了,就會(huì )生成一個(gè)錯誤消息,并在 FacesContext 中進(jìn)行排隊,在產(chǎn)生響應的階段會(huì )顯示其中的消息,同時(shí)還會(huì )顯示所有的驗證錯誤。

處理驗證
生命周期中的第一個(gè)事件處理發(fā)生在應用請求值階段之后。在這個(gè)階段中,每個(gè)組件都有一些值需要根據應用程序的驗證規則進(jìn)行有效性驗證。這些驗證規則可以是預先進(jìn)行定義的(JSF 中提供的),也可以由開(kāi)發(fā)者進(jìn)行定義。用戶(hù)所輸入的值會(huì )與這些驗證規則進(jìn)行比較。如果說(shuō)輸入的值無(wú)效,就會(huì )向 FacesContext 中添加一個(gè)錯誤消息,并且該組件會(huì )被表示為無(wú)效的。如果一個(gè)組件被表示為無(wú)效的,那么 JSF 就會(huì )轉到產(chǎn)生響應的階段,在這個(gè)階段中會(huì )顯示當前的視圖,以及驗證錯誤消息。如果沒(méi)有有效性驗證錯誤,那么 JSF 就會(huì )轉到更新模型值的階段。

階段 3:更新模型值
JSF 應用程序生命周期中的第三個(gè)階段 ——更新模型值 —— 負責更新服務(wù)器端模型的實(shí)際值,通常來(lái)講,這都是通過(guò)更新后臺 bean(稱(chēng)為管理 bean)的屬性實(shí)現的。只有那些與組件值綁定在一起的 bean 屬性才會(huì )被更新。注意這個(gè)階段發(fā)生在有效性驗證之后,因此可以確??截惖?bean 屬性的值都是有效的(至少在表單域一級都是有效的;在業(yè)務(wù)規則一級仍可能無(wú)效)。

階段 4:調用程序
在生命周期的第四個(gè)階段 ——調用程序 —— 中,JSF 控制程序會(huì )調用程序來(lái)處理 表單 的提交操作。組件值已經(jīng)經(jīng)過(guò)了類(lèi)型轉換和有效性驗證,并被應用到模型對象中了,因此您現在可以使用它們來(lái)執行應用程序的業(yè)務(wù)邏輯了。

在這個(gè)階段,您還可以為一個(gè)給定的序列或很多可能的序列指定后面的邏輯視圖,這可以通過(guò)為一次成功的表單提交定義一個(gè)特定的結果并返回這個(gè)結果來(lái)實(shí)現。例如:在成功輸出時(shí),將用戶(hù)重定向到下一頁(yè)中。要讓這種導航工作能夠起作用,您需要在 faces-config.xml 文件中創(chuàng )建一個(gè)到 成功輸出 的映射作為一條導航規則。一旦導航發(fā)生之后,您就轉換到生命周期的最后一個(gè)階段了。

階段 5:進(jìn)行響應
在生命周期的第五個(gè)階段 ——進(jìn)行響應 —— 中,您可以在視圖中顯示當前狀態(tài)中的所有組件。

圖 2 是 JSF 生命周期的第五個(gè)階段的一個(gè)對象狀態(tài)圖,包括時(shí)間有效性驗證和處理。

圖 2. JSF 生命周期的五階段

范例
現在您已經(jīng)對 JSF 生命周期的階段有了基本的了解,下面我們將向您介紹在一個(gè)范例 Web 應用程序中,這些階段是如何協(xié)同工作的。除了展示 JSF 生命周期的基本功能之外,這個(gè)應用程序還會(huì )利用一些通用的 JSF GUI 組件,例如 Radio List, List, Text Field, Label, Panel 等等,這樣您就可以親自體驗一下在 第 1 部分 中曾經(jīng)簡(jiǎn)要討論過(guò)的這些組件。

這個(gè)示例程序還會(huì )展示在 JSF 中使用其他 Javai 技術(shù)的兩種方法。它將組合使用 JSF 和 JavaScript 來(lái)啟用即時(shí)事件處理(在那些對整個(gè)表單進(jìn)行驗證是多余的情況中),其布局是由 Struts Tiles 進(jìn)行管理的。雖然 Struts Tiles 并不是 JSF 的一個(gè)必要部分,但是 tiles 通常用來(lái)為一個(gè)程序中的所有 JSF 頁(yè)面提供一致的外觀(guān)。

程序設置
這個(gè)示例 Web 程序實(shí)際上是一個(gè)非常簡(jiǎn)單的創(chuàng )建、閱讀、更新并刪除(CRUD)一個(gè)在線(xiàn) CD 倉庫中庫存的程序。它包括一個(gè)表單,讓用戶(hù)可以向系統中輸入新 CD;有一些單選按鈕,讓用戶(hù)選擇音樂(lè )的分類(lèi)。當用戶(hù)選擇一個(gè)分類(lèi)時(shí),就啟動(dòng)一些 JavaScript 腳本將這個(gè)表單立即發(fā)回服務(wù)器。程序組合采用 JSF 和 JavaScript 技術(shù)來(lái)處理一個(gè)組件,而不是整個(gè)頁(yè)面,這種技術(shù)稱(chēng)為 即時(shí)事件處理。在這種情況中,您可以填充一個(gè)子類(lèi)清單,而不用驗證表單的其他內容。

這個(gè)示例程序還包括一個(gè) CD 清單,它將展示如何使用 JSF 的 dataTable。從這個(gè)頁(yè)面中,最終用戶(hù)可以根據標題或者藝術(shù)家對 CD 清單進(jìn)行排序。

類(lèi)和方法
 

StoreManagerDelegate 類(lèi)是這個(gè)程序的業(yè)務(wù)代表。它為整個(gè)模型呈現了主界面。CD 類(lèi)是一個(gè)數據轉換對象(DTO)。如果這是一個(gè)真實(shí)的程序,那么 StoreManagerDelegate 類(lèi)就會(huì )為添加、刪除和編輯 CD 實(shí)現所有的業(yè)務(wù)規則,還會(huì )負責使用一個(gè)數據訪(fǎng)問(wèn)對象(DAO)將 CD 存儲到一個(gè)永久的存儲介質(zhì)中。StoreManagerDelegateCD 包含了一些用于這個(gè) MVCi 程序的 模型。

StoreController 類(lèi)是本例中的主要后臺 bean。StoreController 類(lèi)是 GUI 世界和模型世界之間的黏合劑。它將自己的很多行為都委托給 StoreManagerDelegate 進(jìn)行處理。StoreController 是這個(gè) MVC 程序的 控制程序。

StoreController 類(lèi)展示了如何構建一個(gè)可排序的 CRUD 清單。它具有以下與 CRUD 相關(guān)的方法:editCD、addNew、addCD 以及 updateCD。StoreController 還負責將模型對象呈現給表單。在這種情況中,它使用 cd 屬性將當前的 CD 對象呈現給 CD 表單,該屬性的類(lèi)型就是 CD。

開(kāi)始編碼
開(kāi)始編寫(xiě)這個(gè)示例程序的最好方法是遍歷它的使用案例:

  1. 新增 CD
  2. 編輯現有的 CD
  3. 根據標題對 CD 進(jìn)行排序
  4. 根據藝術(shù)家對 CD 進(jìn)行排序

第三個(gè)使用案例和第四個(gè)使用案例的代碼基本上是相同的,因此我將向您展示如何根據標題進(jìn)行排序,并將第四個(gè)使用案例留作練習,請您自行完成。我們很快就會(huì )對使用案例進(jìn)行編碼,但是首先讓我們來(lái)了解一下完成后的應用程序的頁(yè)面將是什么樣子。

使用案例 1:新增 CD
在該程序的第一個(gè)使用案例中,用戶(hù)將添加一個(gè)新 CD:切換到 CD 清單頁(yè)面上,點(diǎn)擊 Add CD 鏈接(這是在 listing.jsp 文件中定義的),如清單 1 所示。

清單 1. 在 listing.jsp 中定義的 Add CD 按鈕

<h:commandLink action="#{CDManagerBean.addNew}">
<f:verbatim>Add CD</f:verbatim>
</h:commandLink>

這個(gè)鏈接被綁定到 CDManagerBeanaddNew 方法上。這個(gè) addNew 方法在 JSF 生命周期的調用程序階段(最后一個(gè)階段)被調用的。操作被使用 JSF 綁定表達式 #{CDManagerBean.addNew} 綁定到這個(gè)方法上。CDManagerBean 是這個(gè)程序的存儲控制器的一個(gè)別名。CDManagerBean 是這個(gè)控制器的邏輯名??刂破黝?lèi)是一個(gè)在 faces-config.xml 文件中定義的管理 bean,如清單 2 所示。

清單 2. 在 faces-config.xml 中定義的 StoreController 類(lèi)

<managed-bean>
<description>The "backing file" bean that backs up the CD application</description>
<managed-bean-name>CDManagerBean</managed-bean-name>
<managed-bean-class>com.arcmind.jsfquickstart.controller.StoreController</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

準備表單
addNew() 方法通過(guò)創(chuàng )建一個(gè)空 CD 來(lái)準備表單,如清單 3 所示。

清單 3. addNew() 創(chuàng )建一個(gè)空 CD 表單

[StoreController.java]
/**
* Prepare the cdForm to add a new CD.
* This gets executed before we prompt
* the user to add a new CD.
*
* @return success
*/
public String addNew() {
if (subCategoryList == null) {
subCategoryList = new HtmlSelectOneListbox();
}

subCategoryList.setRendered(false);
this.cd = new CD();

return "success";
}

addNew() 方法通過(guò)創(chuàng )建一個(gè)新的 CD 來(lái)清空 CD 表單域。這個(gè) CD 表單的域被綁定到 cd 屬性的屬性中。這個(gè)方法還會(huì )將正在顯示的子類(lèi)清單置空。

返回成功結果
接下來(lái),addNew() 方法會(huì )被調用,控制權被重定向到成功映射頁(yè)面,即 cdForm.jsp 文件。cdForm.jsp 文件是在 faces-config.xml 文件中定義的,如清單 4 所示。

清單 4. cdForm.jsp 是 addNew() 的成功映射

<navigation-rule>
<from-view-id>/listing.jsp</from-view-id>
...
<navigation-case>
<from-action>#{CDManagerBean.addNew}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/cdForm.jsp</to-view-id>
</navigation-case>

</navigation-rule>

清單 4 表明如果用戶(hù)從清單切換到 addNew (#{CDManagerBean.addNew}) 操作,并且 addNew 操作成功返回,那就會(huì )切換到 cdForm.jsp 頁(yè)面。

設置 cdForm 和 panelGrid
cdForm.jsp 是包含 CD 表單的表單。其中具有 ID、Title、Artist、Price、Category 和 Subcategory 的域。這些域被放到一個(gè)名為 panelGrid 的容器中。JSF 組件,例如 AWTi 組件,具有一些容器和組件。容器 是一個(gè)包含其他組件的組件。這是一個(gè) 混合設計模式 的例子。panelGrid 有 3 列。每個(gè)域都各在一行中,還會(huì )有一個(gè)標簽和消息用于顯示該域的錯誤消息。cdFormpanelGrid 是在清單 5 中定義的。

清單 5. 定義 cdForm 和 panelGrid

<f:view>
<h2>CD Form</h2>

<h:form id="cdForm">

<h:inputHidden id="cdid" value="#{CDManagerBean.cd.id}"/>

<h:panelGrid columns="3" rowClasses="row1, row2">

<h:outputLabel for="title" styleClass="label">
<h:outputText value="Title"/>
</h:outputLabel>

<h:inputText id="title" value="#{CDManagerBean.cd.title}" required="true"/>

<h:message for="title" styleClass="errorText"/>

<h:outputLabel for="artist" styleClass="label">
<h:outputText value="Artist"/>
</h:outputLabel>

<h:inputText id="artist" value="#{CDManagerBean.cd.artist}" required="true"/>

<h:message for="artist" styleClass="errorText"/>

<h:outputLabel for="price" styleClass="label">
<h:outputText value="Price"/>
</h:outputLabel>

<h:inputText id="price" value="#{CDManagerBean.cd.price}" required="true"/>

<h:message for="price" styleClass="errorText"/>

<h:outputLabel for="category" styleClass="label">
<h:outputText value="Category"/>
</h:outputLabel>

<h:selectOneRadio id="category" value="#{CDManagerBean.cd.category}" immediate="true"
onclick="submit()"
valueChangeListener="#{CDManagerBean.categorySelected}">
<f:selectItems value="#{CDManagerBean.categories}"/>
</h:selectOneRadio>

<h:message for="category" styleClass="errorText"/>

<h:outputLabel for="subcategory" styleClass="label">
<h:outputText value="Subcategory"/>
</h:outputLabel>

<h:selectOneListbox id="subcategory" value="#{CDManagerBean.cd.subCategory}"
binding="#{CDManagerBean.subCategoryList}">
<f:selectItems value="#{CDManagerBean.subCategories}"/>
</h:selectOneListbox>

<h:message for="subcategory" styleClass="errorText"/>

</h:panelGrid>

<br />

<h:commandButton id="submitAdd" action="#{CDManagerBean.addCD}" value="Add CD"
rendered="#{not CDManagerBean.editMode}"/>

<h:commandButton id="submitUpdate" action="#{CDManagerBean.updateCD}" value="Update CD"
rendered="#{CDManagerBean.editMode}"/>

</h:form>

</f:view>

關(guān)于代碼的注釋
每個(gè)輸入域都將該域綁定到控制器的 cd 屬性的一個(gè)屬性上。例如,標題的輸入文本域被使用下面的 JSF 綁定表達式綁定到 cd 屬性上:value="#{CDManagerBean.cd.title}"。

您可能會(huì )注意到在清單 5 中幾乎沒(méi)有什么 HTMLi 語(yǔ)句。這是由于 panelGrid 會(huì )生成大部分的 HMTL 語(yǔ)句。注意實(shí)際的外觀(guān)是由與 panelGrid 相關(guān)的樣式表決定的。屬性 rowClasses="row1, row2" 會(huì )為正在修改的行設置 CSSi 類(lèi)。第一行是白色的,第二行是灰色的。您還可以為列或其他內容指定 CSS 類(lèi)。JSF panelGrid 組件可以方便地快速設置表單的布局。如果您希望實(shí)現 panelGrid 沒(méi)有提供的功能,就不能使用它:不過(guò)可以使用 HTML 自己設置組件的布局。然而,如果您發(fā)現自己在很多頁(yè)面上都使用了定制的 HTML,那么就可能會(huì )考慮編寫(xiě)自己的定制組件。這種想法可以讓您盡可能 DRY 地重用 HTML 語(yǔ)句(DRY 是 don‘t repeat yourself 的縮寫(xiě),這個(gè)術(shù)語(yǔ)來(lái)自于 Dave Thomas 的 Pragmatic Programmer 一書(shū))。

關(guān)于清單 5 另外需要注意的是控制器有一個(gè) editMode 屬性,由 cdForm.jsp 用于有選擇地顯示 submitAdd 按鈕或 submitUpdate 按鈕;submitAdd 按鈕是在表單不處于編輯模式時(shí)顯示的。submitUpdate 按鈕是在表單處于編輯模式時(shí)顯示的。這可以簡(jiǎn)化為編輯和添加模式使用相同的 JSP。(默認情況下,表單不處于編輯模式。)這種功能是由 cdForm.jsp 中的每個(gè)按鈕上的呈現表達式實(shí)現的。例如,清單 6 列出了 submitAdd button rendered="#{not CDManagerBean.editMode}" 上的呈現表達式。submitAdd 按鈕被使用表達式 (action="#{CDManagerBean.addCD}") 綁定到 addCD 方法上。

清單 6. 使用 addCD() 方法添加一個(gè) CD

[StoreController.java]
/**
* Add a cd to the store.
*
* @return outcome
*/
public String addCD() {
store.addCD(this.cd);

return "success";
}

對域進(jìn)行有效性驗證
addCD 方法被調用之前,JSF 必須對 GUI 中的域進(jìn)行有效性驗證。這實(shí)際上非常簡(jiǎn)單,因為您還沒(méi)有為域關(guān)聯(lián)任何有效性驗證條件。在應用請求值階段,這些值被從請求參數拷貝到組件值中(這是由組件本身進(jìn)行的)?,F在,價(jià)格從一個(gè)字符串轉換為一個(gè)浮點(diǎn)類(lèi)型。如果用戶(hù)為價(jià)格輸入的是“abc”,那么轉換為浮點(diǎn)類(lèi)型的操作就會(huì )失敗,控制權將被重新定向到 cdForm.jsp 頁(yè)面上,供最終用戶(hù)進(jìn)行修正。與價(jià)格相關(guān)的 h:message 將顯示一個(gè)轉換錯誤消息。如果所有的值都可以正常進(jìn)行類(lèi)型轉換,并且現在都可以使用了(如果需要的話(huà)),那么您就可以進(jìn)行有效性驗證的處理了。由于這個(gè)示例程序并沒(méi)有與組件關(guān)聯(lián)任何有效性驗證規則(在下一篇文章中我們將介紹這種特性),因此您可以繼續進(jìn)入更新模型值的階段了。

在更新模型值的階段中,會(huì )使用保存在 GUI 組件中的經(jīng)過(guò)轉換和有效性驗證的值來(lái)調用 CD 的賦值方法。addCD() 方法是在 調用程序 階段中被調用的。addCD() 方法使用一個(gè)業(yè)務(wù)代理(store 對象)來(lái)執行這個(gè)操作。addCD 方法在系統中使用 store 對象來(lái)存儲 CD。由于 addCD 方法會(huì )返回成功,因此接下來(lái)會(huì )顯示這個(gè)清單,這是在 faces-config.xm 中定義的。在 faces-config.xml 中定義的導航規則如清單 7 所示。

清單 7. addCD 成功輸出的導航規則

<navigation-rule>
<from-view-id>/cdForm.jsp</from-view-id>
<navigation-case>
<from-action>#{CDManagerBean.addCD}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/listing.jsp</to-view-id>
</navigation-case>
...
</navigation-rule>

使用案例 2:編輯 CD
這個(gè)示例程序的第二個(gè)使用案例也會(huì )在這個(gè)清單頁(yè)面(listing.jsp)中啟動(dòng)。除了向您介紹如何編輯 JSF 頁(yè)面中的數據之外,這個(gè)使用案例還將向您介紹 JSF dataTable 組件。

這個(gè)清單頁(yè)面使用一個(gè) dataTable 組件來(lái)顯示 CD 的清單。dataTable 的值被綁定到控制程序類(lèi) StoreControllercds 屬性。cds 屬性的定義如清單 8 所示。

清單 8. 在 StoreController.java 中定義的 cds 屬性

[StoreController.java]
/** List of cds for CD listing. */
private DataModel cdModel = new ListDataModel();
{
cdModel.setWrappedData(store.findTitleAsc());
}
/**
* List of CDs in the system.
*
* @return Returns the cds.
*/
public DataModel getCds() {
return cdModel;
}

cds 屬性是基于從存儲對象 StoreManagerDelegate 返回的 java.util.List 的,這個(gè)對象是該程序的業(yè)務(wù)代理。cdModel 對從 DataModel 中的存儲對象返回的清單進(jìn)行了封裝。DataModel 是一個(gè)用于 dataTable 的模型。

dataTable 的定義如清單 9 所示。

清單 9. listing.jsp 中的 dataTable 定義

<f:view>
<h:form>
<h:dataTable id="items"
value="#{CDManagerBean.cds}"
var="cd"
rowClasses="oddRow, evenRow"
headerClass="tableHeader">

注意該值被綁定到控制程序的 cds 屬性上。rowClassesheaderClass 屬性用來(lái)指定 CSS 類(lèi),后者用來(lái)定義 dataTable 的外觀(guān)。正如前面介紹的一樣,JSF 嚴重依賴(lài)于 CSS 來(lái)定義 GUI 的外觀(guān)。如果您并不了解 CSS(即您之前都是使用字體標簽和 HTML 表來(lái)設置外觀(guān)的),就可能會(huì )希望在靈活運行 JSF 之前首先來(lái)學(xué)習一下有關(guān) CSS 的知識。

column 組件
Title、ArtistPrice 域都是使用 column 組件顯示的,如清單 10 所示(此處只顯示了 Title 域)。

清單 10. 在 column 組件中添加域

<h:column>
<f:facet name="header">
...
<h:outputText value="Title"/>
</f:facet>
<h:commandLink action="#{CDManagerBean.editCD}">
<h:outputText value="#{cd.title}"/>
</h:commandLink>
</h:column>

column 組件是 dataTable 的一個(gè)子組件。column 組件使用一個(gè)子組件和一個(gè) facet。facet 是一個(gè)有名的子組件;它并不是一個(gè)子孫組件。column 組件有一個(gè)名為 header 的 facet,它定義了在 header 中顯示的內容。對于本例來(lái)說(shuō),commandLinkcolumn 組件的一個(gè)子孫組件。commandLink 在一個(gè)鏈接中顯示了 CD 的標題,該鏈接被綁定到操作 #{CDManagerBean.editCD} 上。這個(gè)操作屬性將 commandLink 綁定到控制程序類(lèi)的 editCD() 方法上,如清單 11 所示。

清單 11. editCD commandLink 的后臺 bean 方法

[StoreController.java]
/**
* Edit the CD. This get executed before the edit cdForm
* page gets loaded.
*
* @return outcome
*/
public String editCD() {
this.cd = (CD) cdModel.getRowData();
this.cd = (CD) store.getCDById(cd.getId());

if ((cd.getCategory() != null) || !"".equals(cd.getCategory())) {
this.subCategoryList.setRendered(true);

this.subCategories = getSubcategoriesList(cd.getCategory());
} else {
this.subCategoryList.setRendered(false);
}

this.editMode = true;

return "success";
}

editCD() 方法
editCD() 方法是在 JSF 生命周期的調用程序階段調用的。editCD() 方法準備控制程序以使用編輯模式來(lái)顯示 cdForm.jsp 頁(yè)面。這是通過(guò)查看當前選定的 CD 來(lái)實(shí)現的,CD 是通過(guò)調用 cdModel.getRowData() 方法來(lái)選擇的。

注意 JSF DataModel 允許您從比傳統的 Web 應用程序更高的層次上使用數據。您并不需要對請求參數進(jìn)行檢查:只需要調用 cdModel.getRowData() 方法向 DataModelcdModel)查詢(xún)已經(jīng)選擇了哪個(gè) CD。這個(gè)更高級別的抽象對 Web 開(kāi)發(fā)進(jìn)行了相當程度的簡(jiǎn)化。

一旦取得當前選擇的 CD 之后,就可以使用業(yè)務(wù)代理來(lái)加載該 CD 的最新拷貝了(store.getCDById())。在加載這個(gè) CD 之后,store.getCDById() 會(huì )激活 subCategory 清單(假設這個(gè) CD 已經(jīng)關(guān)聯(lián)了一個(gè)子目錄),然后將 editMode 屬性設置為 true?;叵胍幌?,editMode 屬性是由 cdForm 用來(lái)顯示 Add 或 Update 按鈕。最后,store.getCDById() 方法返回 success。在清單 12 中重要的導航規則可以保證返回成功之后,切換到 cdForm.jsp 頁(yè)面,如下所示。

清單 12. 一條重要的導航規則

<navigation-rule>
<from-view-id>/listing.jsp</from-view-id>
<navigation-case>
<from-action>#{CDManagerBean.editCD}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/cdForm.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{CDManagerBean.addNew}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/cdForm.jsp</to-view-id>
</navigation-case>
</navigation-rule>

updateCD() 方法
CD 表單會(huì )加載并顯示 CD 屬性的屬性設置。最終用戶(hù)可以根據需要編輯所得到的表單,并在完成時(shí)點(diǎn)擊 Update 按鈕。Update 按鈕是當用戶(hù)處于 Edit 模式時(shí)所顯示的惟一一個(gè)按鈕,它只會(huì )在 editModetrue 時(shí)顯示,如清單 13 所示。

清單 13. Update CD 按鈕

[cdForm.jsp]

<h:commandButton id="submitUpdate"
action="#{CDManagerBean.updateCD}"
value="Update CD"
endered="#{CDManagerBean.editMode}"/>

Update 按鈕被綁定到 updateCD() 方法上。在調用 update 方法之前,JSF 必須對 GUI 中的域進(jìn)行有效性驗證。在應用請求值階段,這些值被從請求參數中拷貝到組件值中(這是由組件本身完成的)?,F在,價(jià)格被從一個(gè)字符串轉換成了一個(gè)浮點(diǎn)類(lèi)型。由于沒(méi)有為組件關(guān)聯(lián)任何有效性驗證規則,因此如果所有請求的值都已經(jīng)存在并經(jīng)過(guò)轉換了,就可以轉換到生命周期的下一個(gè)步驟了。

更新模型值
在更新模型值階段中,會(huì )使用保存在 GUI 組件中經(jīng)過(guò)類(lèi)型轉換和有效性驗證的值來(lái)調用 CD 的賦值函數。updateCD() 方法是在調用程序階段被調用的。updateCD() 方法如清單 14 所示。

清單 14. updateCD() 方法

[StoreController.java]

/**
* Update the CD loaded on the form.
*
* @return success
*/
public String updateCD() {
store.updateCD(this.cd);
this.editMode = false;

return "success";
}

updateCD() 方法可以代理業(yè)務(wù)代理的大部分職責。它將 editMode 設置為 false(這是默認值),并返回成功。成功輸出將您重定向回清單頁(yè)面中,在這個(gè)頁(yè)面中您可以查看根據清單 15 中顯示的導航規則新編輯的 CD。

清單 15. 成功的 UpdateCD 會(huì )將您帶回 listing.jsp

[faces-config.xml]
<navigation-rule>
<from-view-id>/cdForm.jsp</from-view-id>
...
<navigation-case>
<from-action>#{CDManagerBean.updateCD}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/listing.jsp</to-view-id>
</navigation-case>
</navigation-rule>

使用案例 3:對 CD 進(jìn)行排序
我們要介紹的最后一個(gè)使用案例將向您展示如何對表進(jìn)行排序。這個(gè)使用案例也是在 CD 清單頁(yè)面上啟動(dòng)的。清單頁(yè)允許根據標題和藝術(shù)家對 CD 按照升序或降序的順序進(jìn)行排列。在本例中,我將向您展示如何根據標題進(jìn)行排序,并將根據藝術(shù)家進(jìn)行排序留作練習。

標題頭排序有一些到控制程序中排序方法的鏈接。清單 16 顯示了在 listing.jsp 中是如何顯示標題頭的。

清單 16. 對 commandLinks 進(jìn)行排序

[listing.jsp]
<h:column>
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Title"/>
<f:verbatim>     [</f:verbatim>
<h:commandLink styleClass="smallLink" action="#{CDManagerBean.sortTitleAsc}">
<h:outputText id="ascTitle" value="asc"/>
</h:commandLink>
<h:outputText value=","/>
<h:commandLink styleClass="smallLink" action="#{CDManagerBean.sortTitleDec}">
<h:outputText id="decTitle" value="dec"/>
</h:commandLink>
<f:verbatim>]</f:verbatim>
</h:panelGroup>
</f:facet>
<h:commandLink action="#{CDManagerBean.editCD}">
<h:outputText value="#{cd.title}"/>
</h:commandLink>
</h:column>

panelGroup 組件
注意一下清單 16,鏈接是在標題列的 header facet 中定義的。facet 只會(huì )關(guān)聯(lián)一個(gè)惟一名字的組件;這樣,要在 header facet 中放置一個(gè)多鏈接的組件,您需要使用 panelGroup。panelGroup (與 panelGrid 類(lèi)似)是一個(gè)單獨的組件,其中包含了很多子組件。panelGroup 包含兩個(gè)鏈接,如清單 17 所示。

清單 17. panelGroup 組件鏈接

[listing.jsp]
<h:commandLink styleClass="smallLink" action="#{CDManagerBean.sortTitleAsc}">
<h:outputText id="ascTitle" value="asc"/>
</h:commandLink>
...
<h:commandLink styleClass="smallLink" action="#{CDManagerBean.sortTitleDec}">
<h:outputText id="decTitle" value="dec"/>
</h:commandLink>

第一個(gè)鏈接被綁定到控制程序的 sortTitleAsc 方法上,第二個(gè)鏈接被綁定到 sortTitleDec 上。這兩個(gè)方法如清單 18 所示。

清單 18. panelGroup 鏈接方法

[StoreController.java ]
/**
* Uses the store delegate to return
* a sorted list of CDs by title (ascending).
*
* @return asc
*/
public String sortTitleAsc() {
this.cdModel.setWrappedData(store.findTitleAsc());

return "asc";
}

/**
* Uses the store delegate to return
* a sorted list of CDs by title (descending).
*
* @return dec
*/
public String sortTitleDec() {
this.cdModel.setWrappedData(store.findTitleDec());

return "dec";
}

這兩個(gè)方法都依賴(lài)于業(yè)務(wù)代理返回一個(gè)按照正確要求排序后的 java.util.List。注意這個(gè)方法會(huì )返回邏輯輸出 ascdec。這兩個(gè)輸出在 faces-config.xml 文件中都沒(méi)有映射。沒(méi)有映射的輸出會(huì )導致重新加載當前的視圖;這樣,listing.jsp 將會(huì )在調用這些方法時(shí)重新進(jìn)行加載,清單頁(yè)面也會(huì )按照正確的順序重新顯示。

這種方法的優(yōu)點(diǎn)是它依賴(lài)于業(yè)務(wù)代理進(jìn)行排序。業(yè)務(wù)代理又可能會(huì )依賴(lài)于一個(gè) DAOi 對象,而后者又依賴(lài)于一個(gè)數據庫查詢(xún)或 OR 映射查詢(xún),這樣可以對 CD 進(jìn)行有效的查詢(xún)。這種方法通常比具有一個(gè)“智能” GUI 組件的方法更好,后一種方法知道如何對隨機的域對象(CD 就是一個(gè)域對象)進(jìn)行排序,因為排序操作是一個(gè)經(jīng)常發(fā)生的操作,嚴格來(lái)說(shuō),是模型的一部分(即域對象的一部分),而不是視圖的一部分。

正如前面介紹的一樣,對標題進(jìn)行排序和對藝術(shù)家進(jìn)行排序的代碼幾乎是相同的。作為一個(gè)練習,請自己試圖為第四個(gè)使用案例編寫(xiě)代碼,對藝術(shù)家而不是標題進(jìn)行排序。

即時(shí)事件處理
我們要介紹的最后一個(gè)主題是即時(shí)事件處理。即時(shí)事件處理在您不希望(或需要)對整個(gè)頁(yè)面進(jìn)行有效性驗證來(lái)處理用戶(hù)輸入的情況中非常有用?;叵胍幌?,示例程序的 cdForm.jsp 頁(yè)面使用單選按鈕來(lái)顯示一個(gè)目錄和子目錄清單。當最終用戶(hù)選擇一個(gè)目錄時(shí),cdForm.jsp 頁(yè)面就會(huì )使用 JavaScript 重新生成表單,這樣就可以顯示子目錄清單了。

這是一個(gè)即時(shí)事件處理的例子,因為整個(gè)表單 沒(méi)有 在調用事件處理程序之前進(jìn)行有效性驗證。相反,類(lèi)清單的事件處理程序會(huì )生成子目錄,并強制 JSF 跳過(guò)進(jìn)行響應的階段。組件的事件處理程序通常都是在調用程序階段執行的。即時(shí)事件組件的事件處理程序是在應用請求值階段執行的,這發(fā)生在其余組件的類(lèi)型轉換和有效性驗證之前。

清單 19 顯示了在 cdForm.jsp 頁(yè)面中再次顯示的目錄清單。

清單 19. cdForm.jsp 中的目錄清單

[cdForm.jsp]
<h:selectOneRadio id="category" value="#{CDManagerBean.cd.category}"
immediate="true"
onclick="submit()"
valueChangeListener="#{CDManagerBean.categorySelected}">
<f:selectItems value="#{CDManagerBean.categories}"/>
</h:selectOneRadio>

selectOneRadio 目錄域被綁定到 CD 的目錄屬性(value="#{CDManagerBean.cd.category}")上。注意這個(gè)即時(shí)事件處理被激活了(immediate="true")。這種設置意味著(zhù) Category 組件的事件會(huì )在應用值階段(而不是在調用程序階段)進(jìn)行處理(以及類(lèi)型轉換和有效性驗證)。

JavaScript 功能是在 onclick="submit()" 這一行 —— 即當用戶(hù)進(jìn)行修改時(shí),它應該立即被提交到 Web 程序中進(jìn)行處理。

事件處理程序方法
在清單中顯示的可用分類(lèi)是由 f:selectItems 標簽值(value="#{CDManagerBean.categories}")確定的。這個(gè)組件的事件處理程序的變化是控制程序的 categorySelected() 方法(valueChangeListener="#{CDManagerBean.categorySelected}")。事件處理程序如清單 20 所示。

清單 20. categorySelected 事件處理程序

[StoreController.java]
/**
* Event Handler for a category getting selected.
*
* @param event event data
*/
public void categorySelected(ValueChangeEvent event) {
subCategoryList.setRendered(true);

String value = (String) event.getNewValue();

if (value != null) {
this.subCategories = this.getSubcategoriesList(value);
}

FacesContext context = FacesContext.getCurrentInstance();
context.renderResponse();
}

categorySelected() 方法做的第一件事情是允許 subCategoryList 調用自己。categorySelected() 方法然后會(huì )使用所選擇的分類(lèi)值來(lái)查找一個(gè) subCategories 清單。subCategories 屬性被綁定到 subcategoryList 值上。接下來(lái),事件處理程序通過(guò)調用當前 FacesContext 上的 renderResponse() 方法強制 JSF 轉到進(jìn)行響應階段。然后,GUI(cdForm.jsp)為當前顯示的目錄重新顯示可用的子目錄。

將組件綁定到控制程序上
subCategoryList 組件是從 GUI 上綁定的。正如您可以將值綁定到組件上一樣,您也可以將這些組件綁定到一個(gè)控制程序上。子目錄是在 cdForm.jsp 頁(yè)面中定義的,如清單 21 所示。

清單 21. 在 cdForm.jsp 頁(yè)面中定義的子目錄清單

[cdForm.jsp]
<h:selectOneListbox id="subcategory" value="#{CDManagerBean.cd.subCategory}"
binding="#{CDManagerBean.subCategoryList}">
<f:selectItems value="#{CDManagerBean.subCategories}"/>
</h:selectOneListbox>

binding 屬性允許您將 GUI 的組件綁定到后端的 bean(控制程序)上。這樣,上面的組件就會(huì )被綁定到 CDManagerBean.subCategoryList 上,這是在清單 22 中定義的控制程序中的一個(gè)屬性。

清單 22. subCategoryList 屬性

[StoreController.java ]
/** GUI Component that represents
the Subcategory list on the CDForm. */
private UIInput subCategoryList;

{
subCategoryList = new HtmlSelectOneListbox();
}

/**
* Subcategory list component
*
* @param aSubCategoryList The subCategoryList to set.
*
* @uml.property name="subCategoryList"
*/
public void setSubCategoryList(UIInput aSubCategoryList) {
this.subCategoryList = aSubCategoryList;
}

/**
* Subcategory list component
*
* @return Returns the subCategoryList.
*
* @uml.property name="subCategoryList"
*/
public UIInput getSubCategoryList() {
return subCategoryList;
}

即時(shí)事件處理只使用了很少的一點(diǎn) JavaScript 功能(onclick="submit()" 命令),這種靈活的 JSF 生命周期的便利可以讓您處理在一個(gè)組件中輸入的信息,而不用對整個(gè)頁(yè)面進(jìn)行有效性驗證。在這個(gè)例子中,我們已經(jīng)介紹了 Category 組件的即時(shí)處理是如何讓您可以顯示子目錄,而不用重新加載頁(yè)面的。

結束語(yǔ)
在本文中我們使用了一個(gè)范例和三個(gè)使用案例來(lái)介紹 JSF 請求處理的生命周期,并展示了其組件模型的一些必備特性。我們還介紹了如何組合使用 JSF 和 Struts Tiles,在 JSF 頁(yè)面之間實(shí)現更加統一的布局,如何使用 DataModel,以及如何組合使用 JSF 和 JavaScript 進(jìn)行即時(shí)事件的處理。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Facelets 非常適合 JSF(2)
一定要選擇單一技術(shù)嗎?
JSF框架簡(jiǎn)介與實(shí)例
和JSF一起使用JSTL和其它的JSP定制標記
聯(lián)合使用 CSS、JavaScript 和 JSF 精心打造 Ajax 應用程序,第 1 部分: 增強 JSF 頁(yè)面的外觀(guān)
表現層架構的功能和特點(diǎn)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久