首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Spring Web Flow 2.0 入门(9)

Spring Web Flow 2.0 入门(9)

运行应用程序图 5 viewCart.jsp 页面效果用 subflow 实现添加商品到购物车功能商品已经有列表了,接下来就要增加把商品放入购物车的功能,在本示例中用 subflow 来实现这一功能,操作步骤如下:
  • 实现 Cart 和 CartItem 两个业务类
  • 在 shopping.xml 中添加配置
  • 在 /WEB-INF/flows 目录下添加 addToCart.xml
  • 在 webflow-config.xml 中添加 addToCart.xml 的位置
  • 修改 viewCart.jsp 页面
实现 Cart 和 CartItem 两个业务类CartItem 表示存放于购物车中的条目,主要记录相应商品及商品数量,同时不要忘记实现 java.io.Serializable 接口,见清单 29:
清单 29 CartItem 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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++;
    }

    /*省略getter和setter*/

}




除去相应的属性外, CartItem 可根据商品的数量算出该商品的总价格( getTotalPrice ),也可通过 increaseQuantity 增加商品数量。
Cart 是购物车的实现类,其同样要实现 java.io.Serializable 接口,但它没有像 ProductService 一样成为由 Spring IoC 容器管理的 Bean ,每个客户的购物车是不同的,因此不能使用 Spring IoC 容器默认的 Singleton 模式。见清单 30:
清单 30 Cart 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package samples.webflow;

/* 省略 import 语句 */

public class Cart implements Serializable {

    private static final long serialVersionUID = 7901330827203016310L;
    private Map<Integer, CartItem> map = new HashMap<Integer, CartItem>();

    public List<CartItem> getItems() {
        return new ArrayList<CartItem>(map.values());
    }

    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));
     }

    public int getTotalPrice() {
        int total = 0;
        for (CartItem item : map.values())
            total += item.getProduct().getPrice() * item.getQuantity();
        return total;
    }
}




Cart 主要实现三个业务函数, getItems 用于获取当前购物车里的物品, addItem 用于向购物车添加商品, getTotalPrice 用于获取购物车里所有商品的总价格。
在 shopping.xml 中添加配置在 shopping flow 开始时必须分配一个 Cart 对象,由于要调用 subflow ,这个 Cart 对象应存放于 conversationScope 中。同时要添加一个 subflow-state 用于执行添加商品到购物车的任务。
清单 31 shopping.xml 中添加的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<var name="mycart" class="samples.webflow.Cart"/>
<on-start>
  <set name="conversationScope.cart" value="mycart"></set>
</on-start>
<view-state id="viewCart" view="viewCart" >
  <on-render>
    <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>




在 /WEB-INF/flows 目录下添加 addToCart.xml清单 31 中 subflow-state 元素的 subflow 属性即指明了这个被调用的 flow 的 id 为“ addToCart ”,现在就要添加addToCart flow的定义。
清单 32 addToCart.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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">
  <on-start>
    <set name="requestScope.productId" value="requestParameters.productId"/>
  </on-start>
  <action-state id="addToCart">
    <evaluate expression="cart.addItem(productService.getProduct(productId))"/>
    <transition to="productAdded"/>
  </action-state>
  <end-state id="productAdded"/>
</flow>




addToCart flow 主要由一个 action-state 构成,完成添加商品到购物车的功能, addToCart flow 的实现需要有输入参数,即 productId 。在本示例中是通过请求参数来传递,通过 requestParameters 来获取该数值。这里还要注意到清单 32 中的 end-state 的 id 为“ productAdded ”,与清单 31 中 subflow-state 中的 transition元素的on属性的名称是对应的。
在 webflow-config.xml 中添加 addToCart.xml 的位置新增加的 flow 不要忘记在 flow-registry 中注册。
清单 33 flow-registry 中注册 addToCart
1
2
3
4
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
  <webflow:flow-location path="/WEB-INF/flows/shopping.xml" id="shopping"/>
  <webflow:flow-location path="/WEB-INF/flows/addToCart.xml" id="addToCart"/>
</webflow:flow-registry>




修改 viewCart.jsp 页面最后就可以来看在视图中如何显示相关的信息,并触发相应的 webflow 事件,见清单 34:
清单 34 完整的 viewCart.jsp 的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<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>
<ctherwise>
<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>
</ctherwise>
</c:choose>

<a href="${flowExecutionUrl}&_eventId=submit">Submit</a>
<h2>roducts 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>




运行效果图 6 添加购物车后的效果global transition 简介顾名思义, global transition 是一种全局的 transition ,可在 flow 执行的各个 state 中被触发。
清单 35 global-transitons
1
2
3
<global-transitions>
  <transition on="cancelShopping" to="returnToIndex"/>
</global-transitions>




客户端请求中如果包含 _eventId=cancelShopping ,则会重新回到 index.jsp 页面。
返回列表