SpringWebFlow是一个web框架,它适用于元素按规定流程运行的程序;
SpringWebFlow是SpringMVC的扩展,它支持开发基于流程的应用程序。它将流程的定义和实现流程行为的类和视图分离开来。
二、为什么要使用SpringWebFlow?
我们可以使用任何Web框架编写流程化的应用程序,但你会发现流程的定义分散在组成流程的各个元素中,没有地方能够描述整个流程。
三、如何使用SpringWebFlow
流程执行器(flowexecutor)驱动流程的执行。当用户进入一个流程时,流程执行器会为用户创建并启动一个流程执行实例。当流程暂停的时候(如为用户展示视图时),流程执行器会在用户执行操作后恢复流程。如下创建一个流程执行器:
2、配置流程注册表
流程注册表的工作是加载流程定义并让流程执行器能够使用它们。
配置方式一:
配置方式二:
配置FlowHandleMapping帮助将流程请求发送给SpringWebFlow
配置FlowHandlerAdapter响应请求
4、流程的组件
流程是由三个主要元素定义的:状态、转移和流程数据
状态:流程中事件发生的地点;
转移:连接这些点的公路;
数据:流程的当前状况
SpringWebFlow定义了五种不同类型的状态:
行为(Action):行为状态是流程逻辑发生的地方;
决策(Decision):决策状态将流程分成两个方向,它会基于流程数据的评估结果确定流程方向;
结束(End):结束状态是流程的最后一站,一旦进入End状态,流程就会终止;
子流程(Subflow):子流程状态会在当前正在运行的流程上下文中启动一个新的流程;
视图(View):视图状态会暂停流程并邀请用户参与流程;
视图状态:
视图状态用于为用户展现信息并使用户都在流程中发挥作用,实际的试图实现可以是Spring支持的任意视图类型,但通常是用JSP来实现的。
在流程定义的XML文件中,
如果你愿意指定另外一个视图名,那可以使用view属性做到这一点:
行为状态:
视图状态会涉及到流程应用程序的用户,而行为状态则是应用程序自身在执行任务。行为状态一般会触发Spring所管理bean的一些方法并根据方法调用的执行结果转移到另一个状态。
决策状态:
决策状态能够在流程执行时产生两个分支。
在流程定义的xml中,决策状态通过
结束状态:
在流程定义的xml中,结束状态通过
如果结束的流程是一个子流程,那调用它的流程将会从
如果
如果结束的流程不是子流程,也没有指定view属性,那这个流程只是会结束而已,浏览器最后将会加载流程的基本URL地址,当前已没有活动的流程,所以会开始一个新的流程实例。
转移:
转移连接了流程中的状态,流程中除结束状态之外的每个状态,至少都需要一个转移,这样就能够知道一旦这个状态完成时流程要去向哪里。
状态可以有多个转移,分别对应于当前状态结束时可以执行的不同的路径。
转移使用
更常见的转移定义是基于事件的触发来进行的。在视图状态,事件通常会是用户采取的动作;在行为状态,事件是评估表达式得到的结果;在子流程状态,事件取决于子流程结束状态的ID。在任意的事件中,你可以使用on属性来指定触发转移的事件:
流程数据:
创建变量方式一:
创建变量方式三:
5、组合起来:披萨流程
图中的方框代表了状态而箭头代表了转移。
如下的程序清单展示了使用SpringWebFlow的XML流程定义来实现披萨订单的整体流程:
packagecom.chenjl.domain;importjava.io.Serializable;importjava.util.ArrayList;importjava.util.List;publicclassOrderimplementsSerializable{privatestaticfinallongserialVersionUID=1120635411006621502L;privatePaymentpayment;privateList
流程变量order将在前三个状态中进行填充并在第四个状态中进行保存。identifyCustomer子流程状态使用了
在订单得到顾客、一些披萨以及支付细节后,就可以对其进行保存了。saveOrder是处理这个任务的行为状态。它使用
thankCustomer状态是一个简单的视图状态,后台使用了"/WEB-INF/flows/pizza/thankCustomer.jsp"这个JSP文件,如下所示:
SpringWebFlow为视图的用户提供了一个flowExecutionUrl变量,它包含了流程的URL。结束链接将一个“_eventId”参数关联到URL上,以便回到web流程时触发finished事件。这个事件将会让流程到达结束状态。
6、收集顾客信息
在每个披萨订单开始前的提问和回答阶段可以用下面的流程图表示:
使用Web流程识别饥饿的披萨顾客:
按钮名字的"_eventId_"部分是提供给SpringWebFlow的一个线索,它表明接下来要触发事件。当点击这个按钮提交表单时,会触发phoneEntered事件进而转移到lookupCustomer。
查找顾客:
注册新顾客:
registrationForm状态是要求用户填写配送地址的。就像我们之前看到的其他视图状态,它将被渲染成JSP。JSP文件如下所示:
在顾客提供其地址后,我们需要确认他的地址在配送范围之内。如果Spizza不能派送给他们,那么我们要让顾客知道并建议他们自己到店面里取走披萨。
如果顾客在配送区域内的话,那流程转移到addCustomer状态。否则,顾客被带入到deliveryWarning视图状态。deliveryWarning背后的视图就是"/WEB-INF/flows/pizza/customer/deliveryWarning.jsp",如下所示:
存储顾客数据:
当流程抵达addCustomer状态时,用户已经输入了他们的地址。为了将来使用,这个地址需要以某种方式存储起来(可能会存储在数据库中)。addCustomer状态有一个
结束流程:
当customer流程走完所有正常路径后,它最终会到达ID为customerReady的结束状态。当调用它的披萨流程恢复时,它会接收到一个customerReady事件,这个事件将使得流程转移到buildOrder状态。
customerReady结束状态包含了一个
7、构建订单
如下显示了如何将图中所阐述的内容转变成SpringWebFlow定义:
createPizza状态是一个表单视图状态,这个表单可以添加新的Pizza对象到订单中。
有两种方法来结束这个流程。用户可以点击showOrder视图中的Cancel按钮或者Checkout按钮。这两种操作都会使流程转移到一个
8、支付
像订单子流程一样,支付子流程也使用元素接收一个Order对象作为输入。
进入支付子流程的时候,用户会到达takePayment状态。这是一个视图状态,在这里用户可以选择使用信用卡、支票或现金进行支付。提交支付信息后,将进入verifyPayment状态。这是一个行为状态,它将校验支付信息是否可以接受。
使用XML定义的支付流程如下所示:
PaymentType枚举定义如下:
packagecom.chenjl.domain;importjava.util.Arrays;importjava.util.List;publicenumPaymentType{CASH,CHECK,CREDIT_CARD;publicstaticList