上篇博客我们说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. nagios部署+短信和邮件报警

    操作系统 CentOS6.6  服务端:10.0.0.20 客户端:10.0.0.50 一.nagios的服务端安装部署 1.nagios安装 [root@manager src]# rzrz wai ...

  2. hdu 3371(启发式合并的最小生成树)

    Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  3. C#读取JSON字符串

    下面这个是一段JSON字符串宏观图 下面我们通过C#读取JSON字符串里的任何一个数值 string jsonString="上面JSON字符串"; //需要引用Newtonsof ...

  4. AppScan入门工作原理详解

    AppScan,即 AppScan standard edition.其安装在 Windows 操作系统上,可以对网站等 Web 应用进行自动化的应用安全扫描和测试. Rational AppScan ...

  5. geant4开发平台的构建方案的讨论a

    首先比较linux和windows下的平台的不同的功能 linux通过命令进行一系列操作,对于不习惯命令的也可以用鼠标,但是就显得过于落后,因为命令的存在自然表明其先进性. linux下的geant4 ...

  6. IOS8设备连接XCODE6真机调试报错"Could not inspect the application package"

    每次真机调试都要运行2次才行,解决办法:把product name改成英文就行了.

  7. LCIS线段树(区间更新)

    首先线段树每一个节点包含:[b,e],lmax,rmax,max;其中lmax表示从左端点开始连续的最长的增序列长度,rmax表示从e端点开始向左连续的最长下降序列长度,max表示当前区间的连续递增的 ...

  8. python模块打包方法

    http://www.jb51.net/article/92789.htm 一 首先将模块的目录结构整理如下: VASPy/ ├── LICENSE ├── MANIFEST ├── MANIFEST ...

  9. samba 服务实现在windows共享文件

    1. 什么是samba Samba服务类似于windows上的共享功能,可以实现在Linux上共享文件,windows上访问,当然在Linux上也可以访问到. 是一种在局域网上共享文件和打印机的一种通 ...

  10. hive 行转列,列转行

    行转列: concat_ws 列转行: explode