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

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

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

SpringWeb Flow 中的这个 <action-state> 是专为执行业务逻辑而设的 state 。如果某个应用的业务逻辑代码既不适合放在transition 中由客户端来触发,也不适合放在 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

显示效果:

再扩展一下:

如果我们将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的方式来控制页面间的流转顺序以及页面间数据的传输,使得我们页面间的跳转变得更加灵活可控。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 08:57:19

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

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

第一部分demo仅仅介绍了简单的页面跳转,接下来我们要实现与业务逻辑相关的功能. 业务的逻辑涉及到数据的获取.传递.保存,相关的业务功能函数的调用等内容,这些功能的实现都可用Java 代码来完成,但定义 Spring Web Flow 的语法与 Java 是无关的,这就要求 Spring Web Flow 提供与 Java代码的整合机制.要了解这种机制,关键在于搞清楚两个问题: 业务逻辑代码在什么时候被调用? 业务逻辑代码在调用后得到的数据如何保存.传递? 业务逻辑代码在什么时候被调用? 在 S

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

上篇博客我们说Spring web Flow与业务结合的方式主要有三种,以下我们主要介绍一下第三种的应用方式 3,运行到<action-state> 元素 SpringWeb Flow 中的这个 <action-state> 是专为运行业务逻辑而设的 state . 假设某个应用的业务逻辑代码既不适合放在transition 中由client来触发,也不适合放在 Spring Web Flow 自己定义的切入点,那么就能够考虑加入<action-state> 元素专用于

Spring Web Flow 入门demo(一)附源码

Spring Web Flow (SWF)是Spring Framework的一个脱离模块.这个模块是Spring Web应用开发模块栈的一部分,Spring Web包含Spring MVC. Spring Web Flow的目标是成为管理Web应用页面流程的最佳方案.当你的应用需要复杂的导航控制,例如向导,在一个比较大的事务过程中去指导用户经过一连串的步骤的时候,SWF将会是一个功能强大的控制器. 下面我们还是从一个简单的demo开始了解它: 这个例子是结合Springmvc来实现,项目结构:

Web 开发中很实用的10个效果【附源码下载】

在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记得收藏:) 超炫的页面切换动画效果 今天我们想与大家分享一组创意的页面切换熊效果集合.我们已经在示例中罗列了一组动画,可以被应用到页面切换过程中,创造出很有趣的导航效果. 立即下载      在线演示 美!视差滚动在图片滑块中的应用 视差滚动(Parallax Scrolling)已经被广泛应用于网

【转载】Web 开发中很实用的10个效果【附源码下载】

超炫的页面切换动画效果 今天我们想与大家分享一组创意的页面切换熊效果集合.我们已经在示例中罗列了一组动画,可以被应用到页面切换过程中,创造出很有趣的导航效果. 立即下载      在线演示 美!视差滚动在图片滑块中的应用 视差滚动(Parallax Scrolling)已经被广泛应用于网页设计中,这种技术能够让原本平面的网页界面产生动感的立体效果.美女很养眼吧 :) 源码下载      在线演示 网页边栏过渡动画 以细微的过渡动画显示一些隐藏的侧边栏,其余的内容也是.通常侧边栏滑入,把其他内容推

6个Web前端非常精美的flash+xml焦点图(附源码)

1.  flash+xml焦点图代码 源码下载 /  在线演示 2. 开源flash+xml相册组件 源码下载 /  在线演示 3. 可关闭及重复播放泰山压顶广告 源码下载/   在线演示 4. 立体flash滑块 能在支持 FireFox.Chrome.Safari.傲游.搜狗.360浏览器. 源码下载 /   在线演示 5.  平滑切换型flash 源码下载/   在线演示 6. 翻页效果显示flash 源码下载/   在线演示 6个Web前端非常精美的flash+xml焦点图(附源码)

Java之嵌套接口详解(附源码)

示例源码 接口可以嵌套在类或其他接口中.这揭示了许多非常有趣的特性: package com.mufeng.theninthchapter; class A { interface B { void f(); } public class BImp implements B { @Override public void f() { // TODO Auto-generated method stub } } private class BImp2 implements B { @Overrid

spring web flow 2.0入门(转:http://luanxiyuan.iteye.com/blog/2282126)

Spring Web Flow 2.0 入门详解 博客分类: spring 目录: 参考文献 购物车用例 什么情况下可以使用 Spring Web Flow? 配置 Spring Web MVC 配置 Spring Web Flow 2.0 的基础 在购物车示例应用中配置 Spring Web Flow 用 Unified EL 实现业务逻辑 用 subflow 实现添加商品到购物车功能 global transition 简介 1.参考文献 参考1:http://www.ibm.com/dev

Spring Web Flow 学习笔记(2)-流程的组件

1.在Spring Web Flow中,流程由三个主要元素定义的:状态.转移和流程数据. 状态是流程中事件发生的地点,类似公路旅行中停下来的地点,转移就类似与连接这些地点的公路 2.状态 Spring Web Flow 定义了5种不同类型的状态: 状态类型 作用 行为(Action) 是流程逻辑发生的地方 决策(Decision) 将流程分成两个方向,它会基于流程数据的评估结果确定流程的方向 结束(End) 是流程的最后一站,一旦进入End状态,流程就会结束 子流程(Subflow) 会在当前的