上篇博客我们说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. centos7安装gitlab与gitlab的汉化

    Gitlab概述 GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目.  GitLab拥有与Github ...

  2. Codeforces Gym100952 B. New Job (2015 HIAST Collegiate Programming Contest)

      B. New Job   time limit per test 1 second memory limit per test 64 megabytes input standard input ...

  3. 新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)B 杨老师的游戏【暴力/next-permutation函数/dfs】

    链接:https://www.nowcoder.com/acm/contest/116/B 来源:牛客网 题目描述 杨老师给同学们玩个游戏,要求使用乘法和减法来表示一个数,他给大家9张卡片,然后报出一 ...

  4. Jmeter实时性能测试数据的监控

    Jmetet实时性能测试数据的监控和展示Jmeter Grafana InfluxDB 安装Grafana配置jmeter安装InfluxDB配置Grafana展示数据一安装InfluxDB 为了方便 ...

  5. bzoj 1067: [SCOI2007]降雨量

    题目链接: bzoj 1067: [SCOI2007]降雨量 题解: 很简单的一道题,但代码里有许多细节需要注意,切容易出错,调了三个小时OTZ 做一个st表维护区间最大值就 在获得年份在序列中的po ...

  6. php升级版本

    Centos下Yum安装PHP5.5,5.6,7.0 默认的版本太低了,手动安装有一些麻烦,想采用Yum安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | ...

  7. MVC中的Controller中返回一个JsonResult在弹出一个下载框?

    public JsonResult ReturnTest() { return Json(new {myMsg ="hello world"}, "text/html; ...

  8. spring aop expression支持多个表达式配置

    <!-- 配置那些类的方法进行事务管理 --> <aop:config> <aop:pointcut id="allServiceMethod" ex ...

  9. object references an unsaved transient instance - save the transient instance before flushing异常问题处理

    一.异常:org.hibernate.TransientObjectException: object references an unsaved transient instance - save ...

  10. 《JAVA核心卷I》之Java基本程序结构

    Java基本程序结构 1.类名是以大写字母开头的名词代码能够执行的类,要有main函数,且声明必须是public 2.注释:  “//”,"/**/" 行注释  "/** ...