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

第一部分demo仅仅介绍了简单的页面跳转,接下来我们要实现与业务逻辑相关的功能。

业务的逻辑涉及到数据的获取、传递、保存,相关的业务功能函数的调用等内容,这些功能的实现都可用Java 代码来完成,但定义 Spring Web Flow 的语法与 Java 是无关的,这就要求 Spring Web Flow 提供与 Java代码的整合机制。要了解这种机制,关键在于搞清楚两个问题:

  • 业务逻辑代码在什么时候被调用?
  • 业务逻辑代码在调用后得到的数据如何保存、传递?

业务逻辑代码在什么时候被调用?

在 Spring Web Flow中,业务逻辑代码的执行可由以下三种情形来触发:

  • 客户端请求中包含了 _eventId 参数
  • 执行到框架自定义的切入点
  • 执行到 <action-state> 元素

 

1,客户端请求中包含了 _eventId参数

这种方式一般用在state 之间的 transition ,通过指定 _eventId 参数的值,表明了客户的行为,从而导致相应事件的发生,在 Spring Web Flow的定义文件中可以通过 evaluate 元素来指定要处理的业务逻辑

[html]  view plain copy print ?
  1. <transition on="submit">   
  2. <evaluate expression="validator.validate()" />   
  3. </transition>  

当客户端的请求中包含“_eventId=submit ”,则 evaluate 元素中 expression 属性所指明的表达式会被执行,即 validator对象的validate 方法会得到调用。 

2,执行到框架自定义的切入点

SpringWeb Flow 定义了 5 个切入点,通过 flow 定义文件的配置,可在这 5 个切入点插入相关业务逻辑代码。

SpringWeb Flow 自定义的切入点

切入点名称

XML 元素名称

触发时刻

flow start

on-start

flow 执行之前

state entry

on-entry

进入某个 state 之后,做其他事情之前

view render

on-render

在进入 view 的 render 流程之后,在 view 真正 render出来之前

state exit

on-exit

在退出 state 之前

flow end

on-end

flow 执行结束之后

 

on-render 元素

[html]  view plain copy print ?
  1. <view-state id="viewCart" view="viewCart" >  
  2. <on-render>  
  3. <evaluate expression="productService.getProducts()" result="viewScope.products"/>  
  4. </on-render>  
  5. </view-state>  

后续会详细介绍,下面的demo即使用此种方式与业务逻辑建立关系。

 

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

SpringWeb Flow 中的这个 <action-state> 是专为执行业务逻辑而设的 state 。如果某个应用的业务逻辑代码既不适合放在transition 中由客户端来触发,也不适合放在 Spring Web Flow 自定义的切入点,那么就可以考虑添加<action-state> 元素专用于该业务逻辑的执行。

action-state 示例

[html]  view plain copy print ?
  1. <action-state id="addToCart">  
  2. <evaluate expression="cart.addItem(productService.getProduct(productId))"/>  
  3. <transition to="productAdded"/>  
  4. </action-state>  

后续会详细介绍,在下篇博客中会介绍。

 

业务逻辑代码在调用后得到的数据如何保存、传递?

 

Spring Web Flow的定义中可直接使用表达式语言( Expression Language ),前面的代码都是用的 Unified EL ,对于习惯用 OGNL的开发人员,可通过 flow-builder-services 的配置改成使用 OGNL 。不管是哪一种表达式语言, Spring Web Flow都提供了一些固定名称的变量,用于数据的保存、传递。

 

在 Spring Web Flow的解决方案中,我们知道 Spring Web Flow 所着力解决的问题即是数据存取范围的问题,为此, Spring Web Flow提供了两种比较重要的范围,一是 flow 范围,另一个是 conversation 范围。通过 flowScope 和 conversationScope这两个变量, Spring Web Flow 提供了在这两种范围里存取数据的方法。

[html]  view plain copy print ?
  1. <evaluate expression="productService.getProducts()" result="flowScope.products" />    

注意:Spring Web Flow 2.0 在默认配置下,flowScope 和 conversationScope的实现依赖于 Java 序列化和反序列化技术,因此存放于 flowScope 或 conversationScope 中的对象需要实现java.io.Serializable 接口。

注:

  1. flow 范围。此范围内的对象在 flow 开始时创建, flow 结束时销毁,在 flow 定义文件中可通过“ flowScope ”变量名来访问。
  2. conversation 范围。此范围内的对象与 flow 范围对象基本相似,唯一不同在于 conversation 范围内的对象所在的 flow 如果调用了其他 subflow ,那么在 subflow 中也可访问该对象。(也就是说:subflow中能够访问conversation中的对象)


SpringWeb Flow 还提供了大量其他的变量,以方便数据的存取。如 viewScope 范围即是从进入 view-state 至退出 view-state 结束,requestScope 即和一般的 request 范围没什么区别,等等。另外还有一些用于获取 flow 以外数据的变量,如requestParameters 、 messageContext 等等。具体变量的列表可参看 Spring Web Flow自带的文档。

  


Demo实现:


ProductService类

[java]  view plain copy print ?
  1. package samples.webflow;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7.   
  8. import org.springframework.stereotype.Service;  
  9.   
  10. @Service("productService")  
  11. public class ProductService {  
  12.   
  13. private Map<Integer, Product> products = new HashMap<Integer, Product>();  
  14.   
  15. public ProductService() {  
  16. products.put(1new Product(1"Bulldog"1000));  
  17. products.put(2new Product(2"Chihuahua"1500));  
  18. products.put(3new Product(3"Labrador"2000));  
  19. }  
  20.   
  21. public List<Product> getProducts() {  
  22. return new ArrayList<Product>(products.values());  
  23. }  
  24.   
  25. public Product getProduct(int productId) {  
  26. return products.get(productId);  
  27. }  
  28. }  

Service 注解表示 Spring IoC容器会初始化一个名为 productService 的 Bean ,这个 Bean 可在 Spring Web Flow的定义中直接访问。(这也是为什么在web-application-config.xml中添加注解的原因)

 

修改shopping.xml 文件

要在 viewCart 页面中显示商品,只需在view-state 元素的 on-render 切入点调用 productService 的 getProducts 方法,并将所得结果保存到viewScope 中即可。

 

修改后的shopping.xml 

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <flow xmlns="http://www.springframework.org/schema/webflow"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/webflow  
  5.  http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">  
  6.       
  7.     <!-- view-state中的view对应jsp文件夹中的jsp页面,on是触发事件,to对应state id -->  
  8.     <view-state id="viewCart" view="viewCart">  
  9.         <on-render>  
  10.         <!-- 要在 viewCart 页面中显示商品,只需在 view-state 元素的 on-render 切入点调用 productService 的  
  11.          getProducts 方法,并将所得结果保存到 viewScope 中即可 -->  
  12.          <!-- productService 的 getProducts 方法所得的结果会存放在 viewScope 中名为 products 的变量中, jsp 页面的代码可直接访问该变量。 -->  
  13.          <!-- 通过 evaluate 元素来指定要处理的业务逻辑 -->  
  14.             <evaluate expression="productService.getProducts()" result="viewScope.products" />  
  15.         </on-render>  
  16.         <transition on="submit" to="viewOrder">  
  17.         </transition>  
  18.     </view-state>  
  19.       
  20.     <view-state id="viewOrder" view="viewOrder">  
  21.         <transition on="confirm" to="orderConfirmed">  
  22.         </transition>  
  23.     </view-state>  
  24.       
  25.     <view-state id="orderConfirmed" view="orderConfirmed">  
  26.         <transition on="returnToIndex" to="returnToIndex">  
  27.         </transition>  
  28.     </view-state>  
  29.     <end-state id="returnToIndex" view="externalRedirect:servletRelative:/index.jsp">  
  30.     </end-state>  
  31. </flow>  

修改viewCart.jsp 页面

productService的 getProducts 方法所得的结果会存放在 viewScope 中名为 products 的变量中, jsp 页面的代码可直接访问该变量。 

修改后的 viewCart.jsp 页面

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>   
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   
  4. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  5. <html xmlns="http://www.w3.org/1999/xhtml">  
  6. <head>  
  7. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  8. <title>View Cart</title>  
  9. </head>  
  10. <body>  
  11. <h1>View Cart</h1>  
  12. <a href="${flowExecutionUrl}&_eventId=submit">Submit</a>  
  13. <h2>Products for Your Choice</h2>  
  14. <table>  
  15. <c:forEach var="product" items="${products}">  
  16. <tr>  
  17. <td>${product.description}</td>  
  18. <td>${product.price}</td>  
  19. </tr>  
  20. </c:forEach>  
  21. </table>  
  22. </body>  
  23. </html>  


访问地址:http://localhost:8080/CartApp4/spring/index.jsp


View Cart页面效果图:



源码下载

 

总结:

 

以上的代码实现是结合第一篇博客后融合业务逻辑来操作,主要介绍了业务和Spring Web Flow的结合方式,下篇博客将陆续介绍流程的嵌套。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值