一、披萨流程
首先从构建一个高层次的流程开始,它定义了订购披萨的整体流程,然后将其拆分为多个子流程。
1.定义基本流程
当顾客访问Spizza网站时,他们需要进行用户识别、选择一个或多个披萨添加到订单、提供支付信息,然后提交订单,等待披萨上来,如下图:
网上购买披萨的流程
下面展示Spring Web Flow的XML流程定义来实现披萨订单的整体流程:
<?xml version="1.0" encoding="UTF-8"?>
<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-2.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>
流程定义中的第一件事就是声明order变量。每次流程开始的时候都会创建一个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 List<Pizza> pizzas;
private Payment payment;
public Order() {
pizzas = new ArrayList<Pizza>();
customer = new Customer();
}
//getters and setters
}
流程定义的主要组成部分是流程的状态,默认情况下,流程定义文件中的第一个状态会是流程访问的第一个状态。本例中就是identifyCustomer状态(一个子流程)。也可以通过元素的start-state属性来指定任意状态为开始状态:
<?xml version="1.0" encoding="UTF-8"?>
<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-2.3.xsd"
start-state="identifyCustomer">
...
</flow>
识别顾客、构建披萨订单和支付这样的活动比较复杂,并不适合将其直接放在一个状态,而是以元素展现的。 流程变量order将在前3个状态中进行填充并在第4个状态中进行保存。identifyCustomer子流程使用了元素来填充order的customer属性,将其设置为调用顾客子流程收到的输出。buildOrder和takePayment状态使用了不同的方式,它们使用将order流程变量作为输入,这些子流程就能在其内部填充order对象。 在订单得到顾客、披萨以及支付信息后,就可以对其进行保存。saveOrder是处理这个任务的行为状态。它使用来调用ID为pizzaFlowActions的Bean的saveOrder()方法,并将保存的订单对象传递进来。订单完成保存后会转移到thankCustomer。 thankCustomer状态是一个简单的视图状态,后台使用了/WEB-INF/flows/pizza/thankCustomer.jsp文件进行展示: