日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php框架 > 框架設計 > 《Spring實戰》學習筆記-第八章:使用Spring Web Flow

《Spring實戰》學習筆記-第八章:使用Spring Web Flow

來源:程序員人生   發布時間:2016-06-22 08:55:44 閱讀次數:3847次

第4版的第8章內容與第3版基本1致。

本章內容:

  • 創建會話式web利用程序
  • 定義流程狀態和行動
  • 保護web流程

互聯網的1個奇特的地方就在于它很容易讓人迷失。有如此多的內容可以查看和瀏覽,而超鏈接是其強大魔力的核心所在。

有時候,web利用程序需要控制web沖浪者的導向,引導他們1步步地訪問利用。比如電子商務網站的付款流程,從購物車開始,利用程序會引導你順次經過配送詳情、賬單信息和終究的定單確認。

Spring Web Flow是1個web框架,它適用于元素規定流程運行的程序。本章中,我們將會探索它是如何用于Spring Web框架平臺的。

其實我們可使用任何的Web框架編寫流程化的利用程序,比如使用Struts構建特定的流程。但是這樣沒有辦法將流程與實現分開,你會發現流程的定義分散在組成流程的各個元素中,沒有特定的地方能夠完全地描寫全部流程。

Spring Web Flow是Spring MVC的擴大,它支持開發基于流程的利用程序,可以將流程的定義和實現流程行動的類和視圖分離開來。

在介紹Spring Web Flow的時候,我們會暫且放下Spittr樣例,而使用生產披薩定單的web程序。

使用的第1步是在項目中進行安裝,那末就從安裝開始吧。

在Spring中配置Spring Web Flow

Spring Web Flow是基于Spring MVC構建的,這就意味著所有的流程要求都需要經過Spring MVC的DispatcherServlet。我們需要在Spring利用上下文中配置1些Bean來處理流程要求并履行流程。

現在還沒有支持使用Java來配置Spring Web Flow,所以沒得選,只能在XML中進行配置。有1些Bean會使用Spring Web Flow的Spring配置文件命名空間來進行聲明,因此我們需要在上下文定義XML文件中添加相應的命名空間:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.springframework.org/schema/webflow-config" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config⑵.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans⑶.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context⑶.0.xsd">

聲明了命名空間后,就能夠準備裝配Web Flow的Bean了。

編寫流程履行器

顧名思義,流程履行器(flow executor )就是用來驅動流程的履行。當用戶進入到1個流程時,流程履行器會為該用戶創建并啟動1個流程履行器的實例。當流程暫停時(例如為用戶展現視圖時),流程履行器會在用戶履行操作后恢復流程。

在Spring中,元素可以創建1個流程履行器:

雖然流程履行器負責創建和履行流程,但它其實不負責加載流程定義。這個要由流程注冊表(flow registry)負責,下面會創建它。

配置流程注冊表

流程注冊表的工作就是加載流程定義,并讓流程履行器可使用它們。可以在Spring中使用進行配置:

<flow:flow-registry id="flowRegistry" base-path="/WEB-INF/flows"> <flow:flow-location-pattern value="/**/*-flow.xml" /> flow:flow-registry>

正如這里聲明的,流程注冊表會在/WEB-INF/flows目錄下尋覓流程定義,這個路徑是由base-path屬性指明的。根據元素,任何以-flow.xml結尾的XML文件都會被視為流程定義。

所有的流程都是通過其ID來進行援用的。使用元素,流程的ID就是相對base-path的路徑,或是雙星號所代表的路徑,以下圖展現了流程ID是如何計算的:
在使用流程定位模式時,流程定義文件相對于基本路徑的路徑將用作流程的id

另外,你也能夠不使用base-path屬性,直接顯式地聲明流程定義文件的位置:

<flow:flow-registry id="flowRegistry"> <flow:flow-location path="/WEB-INF/flows/springpizza.xml" /> flow:flow-registry>

這里使用了而不是,path屬性直接指定了/WEB-INF/flows/springpizza.xml為流程定義文件。當這樣定義時,流程的ID是從流程定義文件的文件名中獲得的,這就是springpizza。

如果你希望更顯示地指定流程ID,那末可以通過元素的id屬性來進行設置。例如,要設定pizza作為流程ID,可以這樣進行配置:

<flow:flow-registry id="flowRegistry"> <flow:flow-location id="pizza" path="/WEB-INF/flows/springpizza.xml" /> flow:flow-registry>

處理流程要求

正如前面的章節中提到的,DispatcherServlet會將要求分發給控制器,但是對流程而言,你需要FlowHandlerMapping來幫助DispatcherServlet將流程要求發送給Spring Web Flow。FlowHandlerMapping的配置以下:

<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"> <property name="flowRegistry" ref="flowRegistry" /> bean>

FlowHandlerMapping裝配了注冊表的援用,這樣它就知道如何將要求的URL匹配到流程上。例如,如果有1個ID為pizza的流程,FlowHandlerMapping就會知道如果要求的URL是/pizza的話,就會將其匹配到這個流程上。

但是,FlowHandlerMapping的工作僅僅是將流程要求定向到Spring Web Flow,響應要求的是FlowHandlerAdapter,它同等于Spring MVC的控制器,會對流程要求進行響應并處理。FlowHandlerAdapter可以像下面這樣裝配成1個Spring Bean:

<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter"> <property name="flowExecutor" ref="flowExecutor" /> bean>

這個處理適配器就是DispatcherServlet和Spring Web Flow之間的橋梁。它會處理流程要求并管理基于這些要求的流程。在這里,它裝配了流程履行器的援用,而后者是為要求履行流程的。

現在已配置了Spring Web Flow所需的Bean和組件,下面所需的就是真實的定義流程了。首先了解下流程的組成元素。

流程組件

在Spring Web Flow中,流程是由3個主要元素組成的:狀態(state)、轉移(transition)和流程數據(flow data)。狀態是流程中事件產生的地點。如果將流程想象成公路旅行,那末狀態就是路途上的城鎮、路邊飯店和風景點等。流程中的狀態是業務邏輯履行、做出決策或將頁面展現給用戶的地方,而不是在公路旅行中買薯片或可樂這些行動。

如果說流程狀態是公路上停下來的地點,那末轉移就是連接這些點的公路。在流程上,需要通過轉移從1個狀態到達另外一個狀態。

在城鎮間旅行的時候,可能需要購買1些記念品、留下1下回想。類似的,在流程處理進程中,它要搜集1些數據:流程當前狀態等。或許你很想將其稱為流程的狀態,但是我們定義的狀態已有了另外的含義。

狀態

Spring Web Flow定義了5種不同的狀態,以下表所示。通過選擇Spring Web Flow的狀態幾近可以把任意的安排功能構造成會話式的Web利用程序。雖然其實不是所有的流程都需要下表中的狀態,但終究你可能會常常使用其中幾個。

狀態類型 作用
行動(Action) 流程邏輯產生的地方
決策(Decision) 決策狀態將流程分為兩個方向,它會基于流程數據的評估結果肯定流程方向
結束(End) 結束狀態是流程的最后1站,進入End狀態,流程就會終止
子流程(Subflow) 子流程狀態會在當前正在運行的流程上下文中啟動1個新的流程
視圖(View) 視圖狀態會暫停流程并約請用戶參與流程

首先了解下這些流程元素在Spring Web Flow定義中是如何表現的。

視圖狀態

視圖狀態用來為用戶展現信息并使用戶在流程中發揮作用。實際的視圖實現可以是Spring支持的任意視圖類型,但通常是用JSP來實現的。

在流程定義文件中,用來定義視圖狀態:

<view-state id="welcome" />

在這個簡單的示例中,id屬性有兩個含義。其1,它定義了流程中的狀態。其2,由于這里沒有其他地方指定視圖,那末它就指定了流程到達這個狀態時要展現的邏輯視圖名稱為welcome。

如果要顯示地指定另外1個視圖名稱,那末就能夠使用view屬性:

<view-state id="welcome" view="greeting" />

如果流程為用戶展現了1個表單,你希望指定表單所綁定的對象,可使用model屬性:

<view-state id="takePayment" model="flowScope.paymentDetails"/>

這里指定了takePayment視圖將綁定流程范圍內的paymentDetails對象。

行動狀態

視圖狀態包括流程利用的用戶,而行動狀態則是利用程序本身在履行任務。行動狀態1般會觸發Spring所管理Bean的1些方法,并跟你講方法調用的履行結果轉移到另外一個狀態。

在流程定義文件中,行動狀態使用元夙來聲明:

<action-state id="saveOrder"> <evaluate expression="pizzaFlowActions.saveOrder(order)" /> <transition to="thankYou" /> action-state>

雖然沒有嚴格要求,但是元素1般都有1個子元素,該元素給出了行動狀態要做的事情,expression屬性指定了進入這個狀態時要評估的表達式。本例中,給出的是SpEL表達式,這表明它將會找到ID為pizzaFlowActions的Bean,并調用其saveOrder()方法。

決策狀態

流程有可能會依照線性履行下去,從1個狀態到另外一個狀態,沒有其他的替換線路。但是更常見的是流程在某1個點根據流程當前情況進入不同的分支。

決策狀態能夠使得在流程履行時產生兩個分支,它會評估1個Boolean表達式,根據結果是true還是false在兩個狀態轉移當選擇1個。在流程定義文件中,使用元夙來定義決策狀態:

<decision-state id="checkDeliveryArea"> <if test="pizzaFlowActions.checkDeliveryArea(customer.zipCode)" then="addCustomer" else="deliveryWarning" /> decision-state>

其實不是單獨工作的,元素是其核心,它是進行表達式評估的地方,如果表達式結果為true,流程會轉向then屬性指定的狀態,為false會轉向else指定的狀態中。

子流程狀態

或許你不會將利用程序的所有邏輯都寫在1個方法里,而是將其分散到多個類、方法1起其他結構中。

一樣的,將流程分成獨立的部份也是個不錯的主張。元素允許在1個正在履行的流程中調用另外一個流程:

<subflow-state id="order" subflow="pizza/order"> <input name="order" value="order"/> <transition on="orderCreated" to="payment" /> subflow-state>

這里,元素作為子流程的輸入被用于傳遞定單對象。如果子流程結束的狀態ID為orderCreated,那末本流程就會轉移到ID為payment的狀態。

結束狀態

最后,所有的流程都要結束。這就是流程轉移到結束狀態時所做的。元素指定了流程的結束:

<end-state id="customerReady" />

當流程到達時,流程就會結束。接下來產生甚么要取決于以下幾個因素:
- 如果結束的流程是個子流程,那末調用它的流程將會從處繼續履行。的ID將會用作時間觸發從開始的轉移。
- 如果設置了view屬性,那末就會渲染指定的視圖。視圖可以是相對流程的路徑,也能夠是流程模板,使用externalRedirect:前綴的會重定向到流程外部的頁面,而使用flowRedirect:前綴的則會重定向到另外1個流程。
- 如果結束的流程不是子流程也沒有配置view屬性,那末這個流程就會結束。閱讀器最后將會加載流程的基本URL地址,同時,由于沒有活動的流程,所以會開始1個新的流程實例。

需要注意的是1個流程可能有多個結束狀態。由于子流程的結束狀態ID肯定了激活的事件,所以或許你會希望以多種結束狀態來結束子流程,從而能夠在調用流程中觸發不同的事件,即便不是在子流程中,也有可能在結束流程后,根據流程的履行情況有多個顯示頁面供選擇。

下面看1下流程是如何在狀態間遷移的,如何在流程中通過定義轉移來完成道路鋪設。

轉移

如前文所述,轉移連接了流程中的狀態。流程中除結束狀態外的每一個狀態,最少需要1個轉移,這樣就知道在狀態完成時的走向。1個狀態或許有多個轉移,分別表示當前狀態結束時可以履行的不同路徑。

轉移是通過元夙來定義的,作為其他狀態元素(、和)的子元素。最簡單的情勢就是元素在流程中指定下1個狀態:

<transition to="customerReady" />

屬性to用于指定流程中的下1個狀態。如果元素只使用了to屬性,那末這個轉移就會是當前狀態的默許轉移選項,如果沒有其他可用轉移的話,就會使用它。

更加常見的轉移定義是基于事件的觸發來進行的。在視圖狀態,事件通常會是用戶采取的動作。在行動狀態,事件是評估表達式得到的結果。而在子流程狀態,事件取決于子流程結束狀態的ID。在任意事件中,你可使用on屬性來指定觸發轉移的事件:

<transition on="phoneEntered" to="lookupCustomer"/>

在示例中,如果觸發了phoneEntered事件流程,就會進入lookupCustomer狀態。

在拋出異常時,流程也可能進入另外一種狀態。例如,如果沒有找到顧客的記錄,你可能希望流程轉移到1個顯示注冊表單的視圖狀態,以下面:

<transition on-exception="com.springinaction.pizza.service.CustomerNotFoundException" to="registrationForm" />

屬性on-exception和屬性on10分類似,它是指定了要產生轉移的異常而不是1個事件。

全局轉移

在創建完流程后,或許你會發現有些狀態使用了1些通用的轉移。例如在全部流程中到處都有以下轉移:

<transition on="cancel" to="endState" />

與其在多個流程狀態中重復通用的轉移,不如將其作為的子元素,從而作為全局轉移

<global-transitions> <transition on="cancel" to="endState" /> global-transitions>

定義完全局轉移,流程中所有的狀態都會默許具有這個cancel轉移。

流程數據

當流程從1個狀態到達另外一個狀態時,它會帶走1些數據。有時這些數據很快就會被使用,比如直接展現給用戶,有時這些數據需要在全部流程中傳遞并在流程結束時使用。

聲明變量

流程數據是保存在變量中的,而變量可以在流程的任意位置進行援用,并且可以以多種方式進行創建。其中最簡單的方式就是使用元素:

<var name="customer" class="com.springinaction.pizza.domain.Customer"/>

這里創建了1個新的Customer實例并將其放在customer變量中,這個變量可以在流程的任意狀態下進行訪問使用。

作為行動狀態的1部份或說作為視圖狀態的入口,也能夠使用元夙來創建變量:

<evaluate result="viewScope.toppingsList" expression="T(com.springinaction.pizza.domain.Topping).asList()" />

這里元素計算了1個SpEL表達式,并將結果放到toppingsList變量中,這個變量是視圖作用域的。

類似的,元素也能夠設置變量的值:

<set name="flowScope.pizza" value="new com.springinaction.pizza.domain.Pizza()" />

元素與元素類似,都是講變量設置為表達式計算的結果。這里我們設置了1個流程范圍的pizza變量,它的值為Pizza對象的新實例。

流程數據的作用域

流程中所攜帶的數據都有其各自的生命周期,這取決于保存數據的變量本身的作用域,以下表:

范圍 生命周期
Conversation 最高層級的流程開始時創建,在最高層級的流程結束時燒毀。由最高層級的流程和其所有的子流程所同享
Flow 當流程開始時創建,在流程結束時燒毀。只在創建它的流程中是可見的
Request 當1個要求進入流程時創建,流程返回時燒毀
Flash 流程開始時創建,流程結束時燒毀。在視圖狀態解析后,才會被清除
View 進入視圖狀態時創建,退出這個狀態時燒毀,只在視圖狀態內可見

當使用元素聲明變量時,變量始終是流程作用域的,也就是在流程作用域內定義變量。當使用或時,作用域通過name或result屬性的前綴指定。例如,將1個值賦給流程作用域的theAnswer變量:

<set name="flowScope.theAnswer" value="42"/>

到目前為止,我們已看到了Web流程的所有原材料,下面要將其進行整合了,完成1個完全的流程。

組合起來:披薩流程

首先從構建1個高層次的流程開始,它定義了訂購披薩的整體流程,然后將其拆分為多個子流程。

定義基本流程

當顧客訪問Spizza網站時,他們需要進行用戶辨認、選擇1個或多個披薩添加到定單、提供支付信息,然后提交定單,等待披薩上來,以下圖:
網上購買披薩的流程

下面展現Spring Web Flow的XML流程定義來實現披薩定單的整體流程:

<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow⑵.3.xsd"> <var name="order" class="com.springinaction.pizza.domain.Order" /> <subflow-state id="identifyCustomer" subflow="pizza/customer"> <output name="customer" value="order.customer" /> <transition on="customerReady" to="buildOrder" /> subflow-state> <subflow-state id="buildOrder" subflow="pizza/order"> <input name="order" value="order" /> <transition on="orderCreated" to="takePayment" /> subflow-state> <subflow-state id="takePayment" subflow="pizza/payment"> <input name="order" value="order" /> <transition on="paymentTaken" to="saveOrder" /> subflow-state> <action-state id="saveOrder"> <evaluate expression="pizzaFlowActions.saveOrder(order)" /> <transition to="thankCustomer" /> action-state> <view-state id="thankCustomer"> <transition to="endState" /> view-state> <end-state id="endState" /> <global-transitions> <transition on="cancel" to="endState" /> global-transitions> flow>

流程定義中的第1件事就是聲明order變量。每次流程開始的時候都會創建1個Order實例。Order類會包括關于定單的所有信息、顧客信息、訂購的披薩和支付信息等。

package com.springinaction.pizza.domain; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Configurable; @Configurable("order") public class Order implements Serializable { private static final long serialVersionUID = 1L; private Customer customer; private Listpizzas; private Payment payment; public Order() { pizzas = new ArrayList(); customer = new Customer(); } //getters and setters }

流程定義的主要組成部份是流程的狀態,默許情況下,流程定義文件中的第1個狀態會是流程訪問的第1個狀態。本例中就是identifyCustomer狀態(1個子流程)。也能夠通過元素的start-state屬性來指定任意狀態為開始狀態:

<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow⑵.3.xsd" start-state="identifyCustomer"> ... flow>

辨認顧客、構建披薩定單和支付這樣的活動比較復雜,其實不合適將其直接放在1個狀態,而是以元素展現的。

流程變量order將在前3個狀態中進行填充并在第4個狀態中進行保存。identifyCustomer子流程使用了元夙來填充order的customer屬性,將其設置為調用顧客子流程收到的輸出。buildOrder和takePayment狀態使用了不同的方式,它們使用將order流程變量作為輸入,這些子流程就可以在其內部填充order對象。

在定單得到顧客、披薩和支付信息后,就能夠對其進行保存。saveOrder是處理這個任務的行動狀態。它使用來調用ID為pizzaFlowActions的Bean的saveOrder()方法,并將保存的定單對象傳遞進來。定單完成保存后會轉移到thankCustomer。

thankCustomer狀態是1個簡單的視圖狀態,后臺使用了/WEB-INF/flows/pizza/thankCustomer.jsp文件進行展現:

<html xmlns:jsp="http://java.sun.com/JSP/Page"> <jsp:output omit-xml-declaration="yes" /> <jsp:directive.page contentType="text/html;charset=UTF⑻" /> <head><title>Spizzatitle>head> <body> <h2>Thank you for your order!h2> Finish ]]> body> html>

該頁面提供了1個完成流程的鏈接,它展現了用戶與流程交互的唯1辦法。

Spring Web Flow為視圖的用戶提供了1個flowExecutionUrl變量,它包括了流程的URL。結束鏈接將1個_eventId參數關聯到URL上,以便返回到Web流程時觸發finished事件。這個事件將會使流程到達結束狀態。

流程將會在結束狀態完成。由于在流程結束后沒有下1步做甚么具體信息,流程將會重新從identifyCustomer狀態開始,以準備接受下1個定單。

下面還要定義identifyCustomer、buildOrder、takePayment這些子流程。

搜集顧客信息

對1個顧客,需要搜集其電話、住址等信息,以下面的流程圖:
識別顧客流程

這個流程不再是線性的,而是有了分支。例如在查找顧客后,流程可能結束,也可能轉到注冊表單。一樣的,在checkDeliveryArea狀態,顧客可能會被告警,也多是不被告警。

程序清單:

<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow⑵.0.xsd"> <input name="order" required="true" /> <view-state id="welcome"> <transition on="phoneEntered" to="lookupCustomer" /> <transition on="cancel" to="cancel" /> view-state> <action-state id="lookupCustomer"> <evaluate result="order.customer" expression="pizzaFlowActions.lookupCustomer(requestParameters.phoneNumber)" /> <transition to="registrationForm" on-exception="com.springinaction.pizza.service.CustomerNotFoundException" /> <transition to="customerReady" /> action-state> <view-state id="registrationForm" model="order" popup="true"> <on-entry> <evaluate expression="order.customer.phoneNumber = requestParameters.phoneNumber" /> on-entry> <transition on="submit" to="checkDeliveryArea" /> <transition on="cancel" to="cancel" /> view-state> <decision-state id="checkDeliveryArea"> <if test="pizzaFlowActions.checkDeliveryArea(order.customer.zipCode)" then="addCustomer" else="deliveryWarning" /> decision-state> <view-state id="deliveryWarning"> <transition on="accept" to="addCustomer" /> <transition on="cancel" to="cancel" /> view-state> <action-state id="addCustomer"> <evaluate expression="pizzaFlowActions.addCustomer(order.customer)" /> <transition to="customerReady" /> action-state> <end-state id="cancel" /> <end-state id="customerReady" /> flow>

下面將這個流程定義分解成1個個的狀態。

詢問電話號碼

welcome狀態是1個很簡單的視圖狀態,它歡迎訪問Spizza網站的顧客并要求輸入電話。它有兩個轉移:如果從視圖觸發phoneEntered事件,就會定向到lookupCustomer,另外1個就是在全局轉移中定義用來響應cancel事件的cancel轉移。

頁面代碼:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <html> <head> <title>Spring Pizzatitle> head> <body> <h2>Welcome to Spring Pizza!!!h2> <form:form> <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}" /> <input type="text" name="phoneNumber" /> <br /> <input type="submit" name="_eventId_phoneEntered" value="Lookup Customer" /> form:form> body> html>

這個簡單的表單用來讓用戶輸入電話號碼,有兩個特殊的部份,首先是隱藏的_flowExecutionKey輸入。當進入視圖狀態時,流程暫停并等待用戶采取1些行動。當用戶提交表單時,流程履行鍵會在_flowExecutionKey輸入域中返回,并在流程暫停的位置進行恢復。

還需要注意提交按鈕的名稱_eventId_部份是Spring Web Flow的1個線索,它表明了接下來要觸發事件。當點擊這個按鈕提交表單時,就會觸發phoneEntered事件,進而轉移到lookupCustomer。

查找顧客

當歡迎顧客的表單提交后,顧客的電話號碼將包括在要求參數中,并用于查詢顧客。lookupCustomer狀態的元素是查找產生的位置。它將電話號碼從要求參數中抽取出來,并傳遞到pizzaFlowActions Bean的lookupCustomer()方法中。該方法要末返回Customer對象,要末拋出CustomerNotFoundException異常。

在前1種情況下,Customer對象會被設置到customer變量中(通過result屬性)并默許的轉移將流程帶到customerReady狀態。如果沒有查到顧客,那末會拋出異常,流程會轉移到registrationForm狀態。

注冊新顧客

registrationForm要求用戶填寫配送地址:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head><title>Spring Pizzatitle>head> <body> <h2>Customer Registrationh2> <form:form commandName="order"> <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"/> <b>Phone number: b><form:input path="customer.phoneNumber"/><br/> <b>Name: b><form:input path="customer.name"/><br/> <b>Address: b><form:input path="customer.address"/><br/> <b>City: b><form:input path="customer.city"/><br/> <b>State: b><form:input path="customer.state"/><br/> <b>Zip Code: b><form:input path="customer.zipCode"/><br/> <input type="submit" name="_eventId_submit" value="Submit" /> <input type="submit" name="_eventId_cancel" value="Cancel" /> form:form> body> html>

該表單綁定到了Order.customer對象上。

檢查配送區域

顧客提供了地址后,需要確認住址是不是在配送范圍內,因此使用了決策狀態。

決策狀態checkDeliveryArea有1個元素,它將顧客的郵編傳遞到pizzaFlowActions Bean的checkDeliveryArea()方法中,該方法會返回1個Boolean值。

如果顧客在配送范圍內,那末流程將轉移到addCustomer狀態,否則進入deliveryWarning視圖狀態。deliveryWarnin視圖:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head><title>Spring Pizzatitle>head> <body> <h2>Delivery Unavailableh2> <p>The address is outside of our delivery area. The order may still be taken for carry-out.p> <a href="${flowExecutionUrl}&_eventId=accept">Accepta> | <a href="${flowExecutionUrl}&_eventId=cancel">Cancela> body> html>

其中有兩個鏈接,允許用戶繼續定單或取消定單。通過使用與welcome狀態相同的flowExecutionUrl變量,這些鏈接分別觸發流程中的accept和cancel事件。如果發送的是accept事件,那末流程會轉移到addCustomer狀態。否則,子流程會轉移到cancel狀態。

存儲顧客數據

addCustomer有1個元素,它會調用pizzaFlowActions.addCustomer()方法,將order.customer流程參數傳遞進去。

1旦這個流程完成,就會履行默許轉移,流程會轉移到ID為customerReady的結束狀態。

結束流程

當customer流程完成所有的路徑后,會到達customerReady的結束狀態。當調用它的披薩流程恢復時,它會接收到1個customerReady事件,這個事件將使得流程轉移到buildOrder狀態。

注意,customerReady結束狀態包括了1個元素。在流程中,它同等于Java的return語句。它會從子流程中傳遞1些數據到調用流程。例如,元素返回customer變量,這樣披薩流程中的identifyCustomer子流程狀態就能夠將其指定給定單。

另外,如果用戶在任意地方觸發了cancel事件,將會通過cancel狀態結束流程,這也會在披薩流程中觸發cancel事件并致使轉移到披薩流程的結束狀態。

構建定單

下面就是肯定顧客想要甚么樣的披薩,提示用戶創建披薩并將其放入定單,如圖:
通過訂單子流程添加披薩

可以看到,showOrder狀態位于定單子流程的中心位置。這是用戶進入這個流程時的狀態,也是用戶添加披薩定單后轉移的目標狀態。它展現了定單確當前狀態,并允許用戶添加其他的披薩到定單中。

添加披薩定單時,會轉移到createPizza狀態。這是1個視圖狀態,允許用戶對披薩進行選擇。

在showOrder狀態,用戶可以提交定單,也能夠取消。

<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow⑵.0.xsd"> <input name="order" required="true" /> <view-state id="showOrder"> <transition on="createPizza" to="createPizza" /> <transition on="checkout" to="orderCreated" /> <transition on="cancel" to="cancel" /> view-state> <view-state id="createPizza" model="flowScope.pizza"> <on-entry> <set name="flowScope.pizza" value="new com.springinaction.pizza.domain.Pizza()" /> <evaluate result="viewScope.toppingsList"
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 成人在线国产 | 天堂中文字幕在线观看 | 热久久久 | 国产亚洲精品久久久久久 | 国产尤物av尤物在线观看臀 | 午夜精品久久久久久久白皮肤 | 中文字幕一区二区视频 | 国产午夜精品在线观看 | 国产一级片毛片 | 亚洲精品国产成人久久av盗摄 | 精品视频免费在线播放 | 日韩精品成人在线观看 | 国产亚洲欧美在线 | 国产网站在线播放 | 国产日韩精品视频 | 日韩不卡在线观看 | 成人区精品一区二区 | 国产精品区一区二区三区 | 欧美日韩中文字幕在线 | 国产2页 | 国内精品久久久久久久影视简单 | 亚洲欧美一区二区三区国产精品 | 精品久久久久久 | 中文字幕欧美激情 | av 一区二区三区 | 国产一线大片 | 国产午夜精品视频 | 伊人av在线 | 婷婷在线视频 | 成人国产精品免费观看视频 | 欧美日韩电影一区 | 国产成人精品一区二区三区 | 免费在线观看av片 | 国产91在线视频 | 亚洲少妇视频 | 亚洲综合av网 | 亚洲三区在线 | 久久精品 | 国产高清视频 | 紧缚调教一区二区三区视频 | 色网免费观看 |