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

业务的逻辑涉及到数据的获取、传递、保存。相关的业务功能函数的调用等内容,这些功能的实现都可用Java 代码来完毕,但定义 Spring Web Flow 的语法与 Java 是无关的,这就要求 Spring Web Flow 提供与 Java代码的整合机制。

要了解这样的机制。关键在于搞清楚两个问题:

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

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

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

  • client请求中包括了 _eventId 參数
  • 运行到框架自己定义的切入点
  • 运行到 <action-state> 元素

1。client请求中包括了 _eventId參数

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

<transition on="submit">
<evaluate expression="validator.validate()" />
</transition>

当client的请求中包括“_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 元素

<view-state id="viewCart" view="viewCart" >
<on-render>
<evaluate expression="productService.getProducts()" result="viewScope.products"/>
</on-render>
</view-state>

兴许会具体介绍,以下的demo即使用此种方式与业务逻辑建立关系。

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>

兴许会具体介绍,在下篇博客中会介绍。

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

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 提供了在这两种范围里存取数据的方法。

<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类

package samples.webflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.springframework.stereotype.Service; @Service("productService")
public class ProductService { private Map<Integer, Product> products = new HashMap<Integer, Product>(); public ProductService() {
products.put(1, new Product(1, "Bulldog", 1000));
products.put(2, new Product(2, "Chihuahua", 1500));
products.put(3, new Product(3, "Labrador", 2000));
} public List<Product> getProducts() {
return new ArrayList<Product>(products.values());
} public Product getProduct(int productId) {
return products.get(productId);
}
}

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

<?

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"> <!-- view-state中的view相应jsp目录中的jsp页面,on是触发事件,to相应state id -->
<view-state id="viewCart" view="viewCart">
<on-render>
<!-- 要在 viewCart 页面中显示商品,仅仅需在 view-state 元素的 on-render 切入点调用 productService 的
getProducts 方法。并将所得结果保存到 viewScope 中就可以 -->
<!-- productService 的 getProducts 方法所得的结果会存放在 viewScope 中名为 products 的变量中, jsp 页面的代码可直接訪问该变量。 -->
<!-- 通过 evaluate 元素来指定要处理的业务逻辑 -->
<evaluate expression="productService.getProducts()" result="viewScope.products" />
</on-render>
<transition on="submit" to="viewOrder">
</transition>
</view-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>

改动viewCart.jsp 页面

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

改动后的 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>
<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>
</tr>
</c:forEach>
</table>
</body>
</html>

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

View Cart页面效果图:

源代码下载

总结:

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

最新文章

  1. maven学习(中)- 私服nexus搭建
  2. Java程序设计之扑克牌
  3. 避免重定向301&amp;302 (Avoid Redirects)
  4. Doragon Kuesuto 1.15
  5. 黑马程序员——JAVA基础之异常处理机制
  6. hive查询语句
  7. 百度地图API 学习网站
  8. shell脚本实现 视频格式转换 ffmpeg 实现视频转换
  9. How to read video frames in hadoop?如何在Hadoop中读取视频帧?
  10. 几个Uboot命令
  11. Code-Based Configuration (EF6 onwards)
  12. SQL随着子查询结果更新多个字段
  13. Spring的Service层与Dao层解析
  14. 简说raid1 raid2 raid5 raid6 raid10的优缺点和做各自raid需要几块硬盘
  15. CodeForces - 1051D-简单DP
  16. Java 基础之一对象导论
  17. day 31 udp 协议SOCK_DGRAM
  18. 一些css属性的理解和运用。
  19. 使用清华源和阿里源替代Ubuntu源
  20. 团队作业之现场UML设计

热门文章

  1. NPOI 导出excel数据超65535自动分表
  2. AngularJs与Java Web服务器交互
  3. 个人作业-Alpha测试
  4. SQL server 上机练习题
  5. redhat之数据挖掘R语言软件及rstudio-server服务的安装
  6. CAD使用GetXData读数据(网页版)
  7. c++函数进阶
  8. SVN A C D M G U R I 的含义
  9. 调用subprocess调用shell命令时屏蔽标准输出
  10. 原生js实现三个按钮绑定三个计时器,点击其中一个按钮,开启当前计时器,另外另个不开启