上篇博客我们说Spring web Flow与业务结合的方式主要有三种,以下我们主要介绍一下第三种的应用方式

3,运行到<action-state> 元素

SpringWeb Flow 中的这个 <action-state> 是专为运行业务逻辑而设的 state 。

假设某个应用的业务逻辑代码既不适合放在transition 中由client来触发,也不适合放在 Spring Web Flow 自己定义的切入点,那么就能够考虑加入<action-state> 元素专用于该业务逻辑的运行。更倾向于触发某个事件来运行。

action-state 演示样例:

<action-state id="addToCart">
<evaluate expression="cart.addItem(productService.getProduct(productId))"/>
<transition to="productAdded"/>
</action-state>

加入subflow 结点

商品列表已经实现了,接下来操作步骤为:

  1. 实现 Cart 和 CartItem 两个业务类
  2. 在 shopping.xml 中加入配置
  3. 在 /WEB-INF/flows 文件夹下加入 addToCart.xml
  4. 在 webflow-config.xml 中加入 addToCart.xml 的位置
  5. 改动 viewCart.jsp 页面

详细demo实现:

Cart:

package samples.webflow;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; //购物车的实现类
public class Cart implements Serializable { private static final long serialVersionUID = 7901330827203016310L;
private Map<Integer, CartItem> map = new HashMap<Integer, CartItem>(); //getItems 用于获取当前购物车里的物品
public List<CartItem> getItems() {
return new ArrayList<CartItem>(map.values());
} //addItem 用于向购物车加入商品
public void addItem(Product product) {
int id = product.getId();
CartItem item = map.get(id);
if (item != null)
item.increaseQuantity();
else
map.put(id, new CartItem(product, 1));
} //getTotalPrice 用于获取购物车里全部商品的总价格
public int getTotalPrice() {
int total = 0;
for (CartItem item : map.values())
total += item.getProduct().getPrice() * item.getQuantity();
return total;
}
}

Cart 是购物车的实现类,其相同要实现java.io.Serializable 接口。但它没有像 ProductService 一样成为由 Spring IoC 容器管理的 Bean,每一个客户的购物车是不同的,因此不能使用 Spring IoC 容器默认的 Singleton 模式。

CartItem:

package samples.webflow;

import java.io.Serializable;

//购物车中的条目
public class CartItem implements Serializable {
private static final long serialVersionUID = 8388627124326126637L;
private Product product;//商品
private int quantity;//数量 public CartItem(Product product, int quantity) {
this.product = product;
this.quantity = quantity;
} //计算该条目的总价格
public int getTotalPrice() {
return this.quantity * this.product.getPrice();
} //添加商品的数量
public void increaseQuantity() {
this.quantity++;
} /**
* Return property product
*/
public Product getProduct() {
return product;
} /**
* Sets property product
*/
public void setProduct(Product product) {
this.product = product;
} /**
* Return property quantity
*/
public int getQuantity() {
return quantity;
} /**
* Sets property quantity
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
} /* getter setter */ }

shopping.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"> <!-- 在 shopping flow 開始时必须分配一个 Cart 对象,因为要调用 subflow ,
这个 Cart 对象应存放于 conversationScope 中。 同一时候要加入一个 subflow-state 用于运行加入商品到购物车的任务。 -->
<!-- mycart为一个服务类 -->
<var name="mycart" class="samples.webflow.Cart" />
<on-start>
<set name="conversationScope.cart" value="mycart"></set>
</on-start>
<!-- view-state中的view相应jsp文件夹中的jsp页面,on是触发事件,to相应state id -->
<view-state id="viewCart" view="viewCart">
<!-- 在进入 view 的 render 流程之后。在 view 真正 render出来之前 -->
<on-render>
<!-- 要在 viewCart 页面中显示商品,仅仅需在 view-state 元素的 on-render 切入点调用 productService
的 getProducts 方法,并将所得结果保存到 viewScope 中就可以 -->
<evaluate expression="productService.getProducts()" result="viewScope.products" />
</on-render>
<transition on="submit" to="viewOrder" />
<transition on="addToCart" to="addProductToCart" />
</view-state> <subflow-state id="addProductToCart" subflow="addToCart">
<transition on="productAdded" to="viewCart" />
</subflow-state> <view-state id="viewOrder" view="viewOrder">
<transition on="confirm" to="orderConfirmed">
</transition>
</view-state>
<view-state id="orderConfirmed" view="orderConfirmed">
<transition on="returnToIndex" to="returnToIndex">
</transition>
</view-state> <end-state id="returnToIndex" view="externalRedirect:servletRelative:/index.jsp">
</end-state>
</flow>

在/WEB-INF/flows 文件夹下加入 addToCart.xml

subflow-state元素的 subflow 属性即指明了这个被调用的 flow 的 id 为“ addToCart ”,如今就要加入addToCart flow的定义。

addToCart.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"> <!-- flow 运行之前 。productId这个字段内容从viewCart页面中获取-->
<on-start>
<set name="requestScope.productId" value="requestParameters.productId" />
</on-start> <!-- addToCart flow 主要由一个 action-state 构成,完毕加入商品到购物车的功能。
addToCart flow 的实现须要有输入參数。即 productId 。
本演示样例中是通过请求參数来传递。通过 requestParameters 来获取该数值。 这里还要注意到 end-state 的 id 为“ productAdded ”,
与 subflow-state 中的 transition元素的on属性的名称是相应的。 --> <action-state id="addToCart">
<evaluate expression="cart.addItem(productService.getProduct(productId))" />
<transition to="productAdded" />
</action-state>
<end-state id="productAdded" />
</flow>

webflow-config.xml 中加入addToCart.xml 的位置

<?xml version="1.0" encoding="utf-8"?

>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 搜索 samples.webflow 包里的 @Component 注解,并将其部署到容器中 -->
<context:component-scan base-package="samples.webflow" />
<!-- 启用基于注解的配置 -->
<context:annotation-config />
<import resource="webmvc-config.xml" />
<import resource="webflow-config.xml" />
</beans>

viewCart.jsp:

<?xml version="1.0" encoding="utf-8" ?

>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>View Cart</title>
</head>
<body>
<h1>View Cart</h1>
<h2>Items in Your Cart</h2>
<c:choose>
<c:when test="${empty cart.items}">
<p>Your cart is empty.</p>
</c:when>
<c:otherwise>
<table border="1" cellspacing="0">
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr> <c:forEach var="item" items="${cart.items}">
<tr>
<td>${item.product.description}</td>
<td>${item.quantity}</td>
<td>${item.product.price}</td>
<td>${item.totalPrice}</td>
</tr>
</c:forEach> <tr>
<td>TOTAL:</td>
<td></td>
<td></td>
<td>${cart.totalPrice}</td>
</tr>
</table>
</c:otherwise>
</c:choose> <a href="${flowExecutionUrl}&_eventId=submit">Submit</a>
<h2>Products for Your Choice</h2> <table>
<c:forEach var="product" items="${products}">
<tr>
<td>${product.description}</td>
<td>${product.price}</td> <td><a
href="${flowExecutionUrl}&_eventId=addToCart&productId=${product.id}">[add
to cart]</a></td> </tr>
</c:forEach> </table>
</body>
</html>

viewOrder.jsp:

<?xml version="1.0" encoding="utf-8" ?

>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>view order</title>
</head>
<body>
<h1>Order</h1>
<c:choose>
<c:when test="${empty cart.items}">
<p>Your cart is empty.</p>
</c:when>
<c:otherwise>
<table border="1" cellspacing="0">
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr> <c:forEach var="item" items="${cart.items}">
<tr>
<td>${item.product.description}</td>
<td>${item.quantity}</td>
<td>${item.product.price}</td>
<td>${item.totalPrice}</td>
</tr>
</c:forEach> <tr>
<td>TOTAL:</td>
<td></td>
<td></td>
<td>${cart.totalPrice}</td>
</tr>
</table>
</c:otherwise>
</c:choose> <a href="${flowExecutionUrl}&_eventId=confirm">Confirm</a>
</body>
</html>

訪问地址:

http://localhost:8080/CartApp5/spring/index

显示效果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqaW5neXVhbjY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

再扩展一下:

假设我们将shopping.xml中的配置文件改动一下。改为flowScope时。我们在viewOrder页面也能够获取products数据。

<view-state id="viewCart" view="viewCart">
<!-- 在进入 view 的 render 流程之后,在 view 真正 render出来之前 -->
<on-render>
<!-- 要在 viewCart 页面中显示商品,仅仅需在 view-state 元素的 on-render 切入点调用 productService
的 getProducts 方法,并将所得结果保存到 viewScope 中就可以 -->
<evaluate expression="productService.getProducts()" result="flowScope.products" />
</on-render>
<transition on="submit" to="viewOrder" />
<transition on="addToCart" to="addProductToCart" />
</view-state>

viewOrder.jsp:

<h2>Products for Your Choice</h2>

	<table>
<c:forEach var="product" items="${products}">
<tr>
<td>${product.description}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
<a href="${flowExecutionUrl}&_eventId=confirm">Confirm</a>

效果图:

总结:

Spring Web Flow 应用流程的方式攻克了数据存取范围的问题,并在解决数据存取范围问题的同一时候,通过使用xml的方式来控制页面间的流转顺序以及页面间数据的传输,使得我们页面间的跳转变得更加灵活可控。

附源代码

Spring Web Flow 入门demo(三)嵌套流程与业务结合 附源代码的更多相关文章

  1. Spring Web Flow 入门demo(二)与业务结合 附源代码

    第一部分demo仅仅介绍了简单的页面跳转,接下来我们要实现与业务逻辑相关的功能. 业务的逻辑涉及到数据的获取.传递.保存.相关的业务功能函数的调用等内容,这些功能的实现都可用Java 代码来完毕,但定 ...

  2. spring web flow 2.0入门(转)

    Spring Web Flow 2.0 入门 一.Spring Web Flow 入门demo(一)简单页面跳转 附源码(转) 二.Spring Web Flow 入门demo(二)与业务结合 附源码 ...

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

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

  4. Spring Web Flow 2.0 入门

    转载: https://www.ibm.com/developerworks/cn/education/java/j-spring-webflow/index.html 开始之前 关于本教程 本教程通 ...

  5. 笔记41 Spring Web Flow——Demo

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

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

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

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

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

  8. Spring学习笔记4—流程(Spring Web Flow)

    Spring Web Flow是Spring框架的子项目,作用是让程序按规定流程运行. 1 安装配置Spring Web Flow 虽然Spring Web Flow是Spring框架的子项目,但它并 ...

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

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

随机推荐

  1. POJ 3080-Blue Jeans【kmp,字符串剪接】

    Blue Jeans Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20695   Accepted: 9167 Descr ...

  2. 【拓扑排序topsort】【p1226】神经网络

    描述 Description 神经网络就是一张有向图,图中的节点称为神经元,而且两个神经元之间至多有一条边相连,下图是一个神经元的例子: 神经元[编号为1) 图中,X1—X3是信息输入渠道,Y1-Y2 ...

  3. 四. Java继承和多态3. 继承中的方法的覆盖和重载

    在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称.返回值类型.参数列表. 如果在新类中定义一个方法,其名称.返回值类型和参数列表正好与父类 ...

  4. Calendar对象

    1.简单获取年月日 代码示例: package others; import java.util.Calendar; public class CalenderDemo1 { /** * @param ...

  5. Jenkins配置Java项目1(Java+Maven+Tomcat+SVN/Git)

    先收集几个网址,后续再自己动手过一遍 http://www.cnblogs.com/leefreeman/p/4211530.html http://www.cnblogs.com/sunzhench ...

  6. K均值与C均值区别

    k均值聚类:---------一种硬聚类算法,隶属度只有两个取值0或1,提出的基本根据是“类内误差平方和最小化”准则: 模糊的c均值聚类算法:-------- 一种模糊聚类算法,是k均值聚类算法的推广 ...

  7. Tomcat部署多个应用时日志文件路径相同引起的问题

    今天给客户部署新系统,一个 前台应用,一个后台应用,由于用的是同一个架子,日志文件路径也没改,所以两个应用的日志文件是同一个文件,这样应用运行时,就会出现只能访问一个应用的情况,如果两个应用同时访问, ...

  8. Java程序IP v6与IP v4的设置

    Java程序IP v6与IP v4的设置 //Prevent to get IPV6 address,this way only work in debug mode //But you can pa ...

  9. DevExpress控件之popupMenu

    一.首次创建 1.可直接从工具栏拉一个PopupMenu出来, 2.右键Customize,Yes(提示是否自动创建BarManager,并为popupmenu绑定这个BarManager): 3.编 ...

  10. git学习——记录每次更新到仓库

    记录每次更新到仓库 工作目录下面的所有文件都不外乎这两种状态:已跟踪或未跟踪.已跟踪的文件是指本来就被纳入版本控制管理的文件,在上次快照中有它们的记录,工作一段时间后,它们的状态可能是未更新,已修改或 ...