二、订单子流程  

在识别完顾客之后,主流程的下一件事情就是确定他们想要什么类型 的披萨。订单子流程就是用于提示用户创建披萨并将其放入订单中 的,如下图所示。

  showOrder状态位于订单子流程的中心位置。这是用 户进入这个流程时看到的第一个状态,它也是用户在添加披萨到订单 后要转移到的状态。它展现了订单的当前状态并允许用户添加其他的 披萨到订单中。要添加披萨到订单时,流程会转移到createPizza状态。这是另外 一个视图状态,允许用户选择披萨的尺寸和面饼上面的配料。在这 里,用户可以添加或取消披萨,两种事件都会使流程转移回 showOrder状态。  从showOrder状态,用户可能提交订单也可能取消订单。两种选择 都会结束订单子流程,但是主流程会根据选择不同进入不同的执行路 径。

订单子流程定义,用于展示订单和添加披萨。

 <?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.0.xsd"> <input name="order" required="true" /> <!-- Order -->
<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"
expression="T(com.springinaction.pizza.domain.Topping).asList()" />
</on-entry>
<transition on="addPizza" to="showOrder">
<evaluate expression="order.addPizza(flowScope.pizza)" />
</transition>
<transition on="cancel" to="showOrder" />
</view-state> <!-- End state -->
<end-state id="cancel" />
<end-state id="orderCreated" />
</flow>

  这个子流程实际上会操作主流程创建的Order对象。因此,我们需要以某种方式将Order从主流程传到子流程。在这里,使用<input>元素来接收Order对象。如果你觉得这个流程与Java中的方法有 些类似地话,那这里使用的<input>元素实际上就定义了这个子流 程的签名。这个流程需要一个名为order的参数。 showOrder状态,它是一个基本的视图状态并 具有三个不同的转移,分别用于创建披萨、提交订单以及取消订单。

  createPizza状态更有意思一些。它的视图是一个表单,这个表单 可以添加新的Pizza对象到订单中。<on-entry>元素添加了一个新 的Pizza对象到流程作用域内,当表单提交时,表单的内容会填充到 该对象中。需要注意的是,这个视图状态引用的model是流程作用域 内的同一个Pizza对象。Pizza对象将绑定到创建披萨的表单中,如 下所示。

通过将流程作用域的对象绑定到HTML表单,实现 添加披萨到订单中。

createPizza.jsp

 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<div> <h2>Create Pizza</h2>
<form:form commandName="pizza">
<input type="hidden" name="_flowExecutionKey"
value="${flowExecutionKey}" /> <b>Size: </b>
<br />
<form:radiobutton path="size" label="Small (12-inch)" value="SMALL" />
<br />
<form:radiobutton path="size" label="Medium (14-inch)" value="MEDIUM" />
<br />
<form:radiobutton path="size" label="Large (16-inch)" value="LARGE" />
<br />
<form:radiobutton path="size" label="Ginormous (20-inch)"
value="GINORMOUS" />
<br />
<br /> <b>Toppings: </b>
<br />
<form:checkboxes path="toppings" items="${toppingsList}"
delimiter="<br/>" />
<br />
<br /> <input type="submit" class="button" name="_eventId_addPizza"
value="Continue" />
<input type="submit" class="button" name="_eventId_cancel"
value="Cancel" />
</form:form>
</div>

  当通过当通过Continue按钮提交订单时,尺寸和配料选择将会绑定 到Pizza对象中并且触发addPizza转移。与这个转移关联的 <evaluate>元素表明在转移到showOrder状态之前,流程作用域 内的Pizza对象将会传递给订单的addPizza()方法中。

  有两种方法来结束这个流程。用户可以点击showOrder视图中的 Cancel按钮或者Checkout按钮。这两种操作都会使流程转移到一个 <end-state>。但是选择的结束状态id决定了退出这个流程时触发 事件,进而最终确定了主流程的下一步行为。主流程要么基于 cancel事件要么基于orderCreated事件进行状态转移。在前者情 况下,外边的主流程会结束;在后者情况下,它将转移 到takePayment子流程。

三、支付

  在披萨流程要结束的时候,最后的子流程提示用户输入他们的支付信息。这个简单 的流程如下图所示。

  支付子流程也使用<input>元素接收一 个Order对象作为输入。

  进入支付子流程的时候,用户会到达takePayment状 态。这是一个视图状态,在这里用户可以选择使用信用卡、支票或现 金进行支付。提交支付信息后,将进入verifyPayment状态。这是 一个行为状态,它将校验支付信息是否可以接受。

  使用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.0.xsd"> <input name="order" required="true"/> <view-state id="takePayment" model="flowScope.paymentDetails">
<on-entry>
<set name="flowScope.paymentDetails"
value="new com.springinaction.pizza.domain.PaymentDetails()" /> <evaluate result="viewScope.paymentTypeList"
expression="T(com.springinaction.pizza.domain.PaymentType).asList()" />
</on-entry>
<transition on="paymentSubmitted" to="verifyPayment" />
<transition on="cancel" to="cancel" />
</view-state> <action-state id="verifyPayment">
<evaluate result="order.payment" expression=
"pizzaFlowActions.verifyPayment(flowScope.paymentDetails)" />
<transition to="paymentTaken" />
</action-state> <!-- End state -->
<end-state id="cancel" />
<end-state id="paymentTaken" />
</flow>

  在流程进入takePayment视图时,<on-entry>元素将构建一个支付表单并使用SpEL表达式在流程作用域内创建一 个PaymentDetails实例,这是支撑表单的对象。它也会创建视图 作用域的paymentTypeList变量,这个变量是一个列表包含了 PaymentType枚举(如下所示)的值。在这里,SpEL的 T()操作用于获得PaymentType类,这样就可以调用静态的 asList()方法。

 package com.springinaction.pizza.domain;

 import java.util.Arrays;
import java.util.List; import org.apache.commons.lang3.text.WordUtils; public enum PaymentType {
CASH, CHECK, CREDIT_CARD; public static List<PaymentType> asList() {
PaymentType[] all = PaymentType.values();
return Arrays.asList(all);
} @Override
public String toString() {
return WordUtils.capitalizeFully(name().replace('_', ' '));
}
}

  在面对支付表单的时候,用户可能提交支付也可能会取消。根据做出的选择,支付子流程将以名为paymentTaken或cancel的<end-state>结束。就像其他的子流程一样,不论哪种<end-state>都 会结束子流程并将控制交给主流程。但是所采用<end-state>的id 将决定主流程中接下来的转移。

笔记40 Spring Web Flow——订单流程(构建订单)的更多相关文章

  1. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  2. 笔记38 Spring Web Flow——订单流程(定义基本流程)

    做一个在线的披萨订购应用 实际上,订购披萨的过程可以很好地定义在一个流程中.我们首先从 构建一个高层次的流程开始,它定义了订购披萨的整体过程.接下 来,我们会将这个流程拆分成子流程,这些子流程在较低的 ...

  3. 笔记39 Spring Web Flow——订单流程(收集顾客信息)

    如果你曾经订购过披萨,你可能会知道流程.他们首先会询问你的电 话号码.电话号码除了能够让送货司机在找不到你家的时候打电话给 你,还可以作为你在这个披萨店的标识.如果你是回头客,他们可以 使用这个电话号 ...

  4. 笔记37 Spring Web Flow——流程的组件

    在Spring Web Flow中,流程是由三个主要元素定义的:状态.转移和 流程数据. 一.状态 Spring Web Flow定义了五种不同类型的状态.通过选择Spring Web Flow的状态 ...

  5. 笔记42 Spring Web Flow——Demo(2)

    转自:https://www.cnblogs.com/lyj-gyq/p/9117339.html 为了更好的理解披萨订购应用,再做一个小的Demo. 一.Spring Web Flow 2.0新特性 ...

  6. 笔记43 Spring Web Flow——订购披萨应用详解

    一.项目的目录结构 二.订购流程总体设计 三.订购流程的详细设计 1.定义基本流程pizza-flow.xml <?xml version="1.0" encoding=&q ...

  7. 笔记41 Spring Web Flow——Demo

    订购披萨的应用整体比较比较复杂,现拿出其中一个简化版的流程:即用户访问首页,然后输入电话号(假定未注册)后跳转到注册页面,注册完成后跳转到配送区域检查页面,最后再跳转回首页.通过这个简单的Demo用来 ...

  8. 笔记36 Spring Web Flow——配置

    Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序.Spring Web Flow是Spring MVC的扩展,它支持开发基于流程的应用程 序.它将流程的定义与实现流程行 ...

  9. Spring Web Flow 入门demo(三)嵌套流程与业务结合 附源代码

    上篇博客我们说Spring web Flow与业务结合的方式主要有三种,以下我们主要介绍一下第三种的应用方式 3,运行到<action-state> 元素 SpringWeb Flow 中 ...

随机推荐

  1. 【Neo4j查询优化系列】如何快速统计节点的关系数

    在图数据库中我们经常需要统计节点上的关系数目.一种常见的查询写法是这样的: MATCH (n:Person {name:'Keanu Reeves'})-[]-() RETURN count(*); ...

  2. npm install 时 提示err code EINTEGRITY报错

    1.报错截图如图: 2.报错缘由:因npm 版本问题导致 3.解决方法:升级npm版本(npm i -g npm),再重新npm install即可.

  3. 【读书笔记】【数据库】SQL必知必会

    第1课 了解SQL 简单介绍了sql,和dbms,无重点. 第2课 检索数据 重点:select语句,distinct,limit,注释 1. select 语句如果没有明确排序查询结果,那么返回的数 ...

  4. 路由网关--spring cloud zuul

    路由网关--spring boot Zuul 1.为什么需要Zuul? Zuul Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能, Zuul 能够将请求流量按某种策略分发到 ...

  5. javascript onclick事件可以调用两个方法吗?

    答案是:可以的,onclick事件可以调用多个方法,每个方法之间用分号(:)隔开即可. onclick后面其实是可以写任何代码的,但是一般不建议这么写!! 例:onclick="fun1() ...

  6. loadrunner自定义函数

    https://zhangfy068.iteye.com/blog/1614794 Loadruner 有四种实现自定义函数的方式,根据脚本编写方便性进行选择不同的方式. (1)直接引用法: Acti ...

  7. 每天一个Linux命令:man(0)

    man man命令是Linux下的帮助指令,通过man指令可以查看Linux中的指令帮助.配置文件帮助和编程帮助等信息. 格式 man [-adfhktwW] [section] [-M path] ...

  8. git stash 保存和恢复进度

    1. stash当前修改 git stash会把所有未提交的修改(包括暂存的和非暂存的)都保存起来,用于后续恢复当前工作目录. 比如下面的中间状态,通过git stash命令推送一个新的储藏,当前的工 ...

  9. 理解CommonJS ,AMD ,CMD, 模块规范

    参考 : https://blog.csdn.net/xcymorningsun/article/details/52709608 1.CommonJS 模块规范 (同步加载模块): var math ...

  10. TI低功耗蓝牙(BLE)介绍【转】

    转自:http://blog.csdn.net/ooakk/article/details/7302425 TI低功耗蓝牙(BLE)介绍 本文档翻译和修改自参考资料:CC2540Bluetooth L ...