zoukankan      html  css  js  c++  java
  • Spring Web Flow 入门demo(三)嵌套流程与业务结合 附源代码


    上篇博客我们说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

     

    显示效果:



    再扩展一下:


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


    附源代码




  • 相关阅读:
    java synchronized详解
    android 刷新系统资源库
    android4.1 源码 支持的 时区
    Logcat过滤及常见用法整理
    Android系统 广播Intent 小结
    android adb push 与 adb install 区别(两种安装APK的方法)
    Intent的常用Flag参数:
    java里的 thread 源码
    instanceof 运算符 小结
    Android下屏保程序的开发须知
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7258998.html
Copyright © 2011-2022 走看看