Spring Web Flow 是Spring MVC 的扩展,它支持开发基于流程的应用程序。它将流程的定义与实现流程行为的类和视图分离开来。

1.配置Web Flow

在Spring MVC上下文定义,添加的命名空间:

 xmlns:flow="http://www.springframework.org/schema/webflow-config"xsi:schemaLocation="http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow=config/spring-webflow-config-2.3.xsd

完整配置:

<?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:flow="http://www.springframework.org/schema/webflow-config"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd"><!-- flow-executor流程执行器 --><flow:flow-executor id="flowExecutor"/><!-- 流程注册表 --><flow:flow-registry id="flowRegistry" base-path="/WEB-INF/flows"><flow:flow-location-pattern value="*-flow.xml"/><!-- 这样,结合base-path属性,凡是在base-path下,且以-flow.xml结尾的文件都将视为流程定义 --><!-- 当然,也可以不要base-path,像下面这样直接定义 ,id可以不写,访问这个流程的时候用/id即可--><flow:flow-location path="/WEB-INF/flows/springpizza.xml" id="pizza"/></flow:flow-registry><!-- 定义HandlerMapping --><bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"><property name="flowRegistry" ref="flowRegistry"/></bean><!-- 定义HandlerAdapter --><bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter"><property name="flowExecutor" ref="flowExecutor"/></bean>
</beans>

流程执行器:会为用户创建并启动一个流程执行实例。当流程暂停的时候(如为用户展示视图时),流程执行器会在用户执行操作后恢复流程。
流程注册表:加载流程定义文件并让流程执行器能够使用它们。
个人认为,Spring WebFlow的实现的核心就是基于其实现了HandlerMapping和HandlerAdapter。

2.流程组件

流程是由三个主要元素定义的:状态、转移和流程数据。状态是流程中事件发生的地点。转移用来连接状态。流程数据是流程的当前状况。

2.1 状态

Spring Web Flow定义了五种不同类型的状态:

状态类型 它是用来做什么的
行为(Action) 行为状态时流程逻辑发生的地方
决策(Decision) 决策状态将流程纷飞两个方向,他是基于流程数据的评估结果来确定流程方向
结束(end) 结束状态时流程的最后一站,一旦进入结束状态,流程就会终止
子流程(Subflo) 子流程状态会在当前正在运行的流程上下文中启动一个新的流程
视图(view) 视图状态会暂停流程并邀请用户参与流程

视图状态:

<view-state id="welcome" view="greeting" model="flowScope.paymentDetail"/>

id属性标示这个状态,除此之外,如果没有定义view属性,则将自动默认view属性为id属性。model属性表明逻辑视图名greeting所表示的视图中的表单将绑定流程作用域中的paymentDetail对象。

行为状态:

<action-state id="saveOrder">
<evaluate expression="pizzaFlowActions.saveOrder(order)" />
<transition to="thankyou" />
</action-state>

上面<evaluate>给出了行为状态要做的事情。expression属性指定了进入状态时要评估的表达式,这里使用的SpEL表达式,表明将会找到ID为pizzaFlowActions的bean并调用其saveOrder()方法。

决策状态:

<decision-state id="checkDeliverArea">
<if test="pizzaFlowActions.checkDeliverArea(customer.zipCode)"than="addCustomer"else="deliverWarning" />
</decision-state>

子流程状态:

<subflow-state id="order" subflow="pizza/order">
<input name="order" value="order" />
<transition on="orderCreated" to="payment" />
</subflow-state>

在这里,<input />元素用于传递订单对象作为子流程的输入,如果子流程结束的<end-state>状态ID为orderCreated,那么流畅将会转移到名为payment的状态。

结束状态:

<end-state id="customerReady" />

当到达<end-state>状态,流程会结束。接下来会发生什么取决于几个因素:

  • 如果结束的流程是一个子流程,那调用它的流程将会从<subflow-state>处继续执行,<end-state>的ID将会用作事件触发从<subflow-state>开始的转移。
  • 如果<end-state>设置了view属性,指定的视图将会被渲染。视图可以是相对于流程路径的视图模板,如果添加“externalRedirect:”前缀的话,将会重定向到流程外部的页面,如果添加“flowRedirect:”将重定向到另外一个流程中。
  • 如果结束的流程不是子流程,也没有指定view属性,那这个流程只是会结束而已。浏览器最后将会加载流程的基本URL地址,当前已没有活动的流程,所以会开始一个新的流程实例。

2.2转移

流程中除结束状态之外的每个状态,至少都需要一个转移,这样就能够知道一旦这个状态完成时流程要去向哪里。状态可以有多个转移,分别对应于当前状态结束时可以执行的不同的路径。

<transition to="customerReady" on="phoneEntered"/>

to属性指定流程的下一个状态,必须。on属性指定触发转移的事件,非必须。
还可以使用on-exception属性指定抛出异常时进入另一个状态。

<transition on-exception="com.springination.pizza.service.CustomNotFoundException" to="registrationForm" />

全局转移(流程中的所有状态都会默认拥有这个转移):

<globl-transitions><transition on="cancel" to="endState" />
</global-transitions>

2.3流程数据

声明变量:
使用<var>

<var name="customer" class="com.xxx.Customer" />

使用set

<set name="flowScope.pizza"value="new com.xx.Pizza()" />

作为行为状态的一部分或者作为视图状态的入口,可以使用evaluate元素来创建变量:

<evaluate result="viewScope.toppingsList"expression="T(com.xxx.Topping).asList()" />

这里计算了一个表达式SpELl并将结果放到了名为toppingList的变量中,这个变量是视图作用域的。
set和evaluate元素很类似,都是讲变量设置为表达式计算的结果。
Spring WebFlow的作用域:

范围 生命作用域和可见性
Conversation 最高层级的流程开始时创建,在最高层级的流程结束时销毁。被最高层级的流程和其所有的子流程所共享
Flow 当流程开始时创建,在流程结束时销毁。只有在创建它的流程中是可见的
Request 当一个请求进入流程时创建,在流程返回时销毁
Flash 当流程开始时创建,在流程结束时销毁。在视图状态渲染后,它也会被清除
View 当进入视图状态时创建,当这个状态退出时销毁,只是在视图状态内是可见的

当时用<var>元素声明变量时,变量始终是流程作用域,也就是在定义变量的流程内有效。当使用<set><evaluate>的时候,作用域通过name或result属性的前缀指定。

<set name="flowScop.theAnswer" value="32">

3.案例

按照书上做的一个订购披萨的流程Demo,Demo下载链接:http://download.csdn.net/detail/csdn_xuexiaoqiang/9798188,搭建好后流程的访问地址是“localhost:8080/spizza/pizza”。


2017-4-24 21:50:42补充集成

4.Spring MVC和Spring Web Flow集成

只需要配置两个DispatcherServlet就可以了。
下面是web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance http://www.springmodules.org/schema/cache/springmodules-cache.xsd http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  <context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 这个服务普通的MVC请求 --><servlet><servlet-name>spring</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:dispatcherServlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup>  </servlet><servlet-mapping><servlet-name>spring</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping><!-- 这个服务流程请求 --><servlet><servlet-name>pizzaServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:pizaarServlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup> </servlet><servlet-mapping><servlet-name>pizzaServlet</servlet-name><url-pattern>/flow/*</url-pattern></servlet-mapping>
</web-app>

配置文件pizaarServlet-context.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:flow="http://www.springframework.org/schema/webflow-config"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd"><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/"/><property name="suffix" value=".jsp"/></bean><!-- flow-executor流程执行器 --><flow:flow-executor id="flowExecutor"/><!-- 流程注册表 --><flow:flow-registry id="flowRegistry"><flow:flow-location path="/WEB-INF/pizza-flow.xml" id="pizza"/><flow:flow-location path="/WEB-INF/customer-flow.xml" id="customer"/><flow:flow-location path="/WEB-INF/order-flow.xml" id="order"/><flow:flow-location path="/WEB-INF/payment-flow.xml" id="payment"/></flow:flow-registry><!-- 定义HandlerMapping --><bean id="handlerMapping" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"><property name="flowRegistry" ref="flowRegistry"/></bean><!-- 定义HandlerAdapter --><bean id="handlerAdapter" class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter"><property name="flowExecutor" ref="flowExecutor"/></bean>
</beans>

配置文件dispatcherServlet-context.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:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/"/><property name="suffix" value=".jsp"/></bean><context:component-scan base-package="com.pizza.action"/></beans>

这样就可以了。通过localhost:8080/spizza/flow/pizza这个链接就可以访问我们定义的披萨流程。
通过localhost:8080/spizza/index.do就可以访问下面这个controller:

@Controller
public class Index {@RequestMapping("/index.do")public void test(){System.out.println("MVC测试成功");}
}

Spring学习笔记之Spring Web Flow相关推荐

  1. Spring学习笔记 之 Spring<全>

    开始学习Spring全家桶 文章目录 1. IoC 定义 为什么叫控制反转? 实现 IoC 容器创建 bean 的两种⽅式 IoC DI 特殊字符的处理 Spring 中的bean创建类型 -- sc ...

  2. spring学习笔记(spring概述和IOC)

    spring5 1.spring的概述 1.1.spring是什么 Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,它是为了解决企业应用开发的复杂性而创建的. Spring 的 ...

  3. spring学习笔记 -- day02 spring基础、IOC控制反转

    一:srping的介绍 1.spring的体系结构 2.spring资源 a.spring-framework-4.2.4.RELEASE:Spring Framework的官方发行包 b.sprin ...

  4. Spring学习笔记:Spring整合Mybatis(mybatis-spring.jar)(二:mybatis整合spring)

    http://blog.csdn.net/qq598535550/article/details/51703190 二.Spring整合mybatis其实是在mybatis的基础上实现Spring框架 ...

  5. spring学习笔记06-spring整合junit(出现的问题,解决的思路)

    spring学习笔记06-spring整合junit(出现的问题,解决的思路) 文章目录 spring学习笔记06-spring整合junit(出现的问题,解决的思路) 3.1测试类中的问题和解决思路 ...

  6. spring学习笔记02-spring-bean创建的细节问题

    spring学习笔记02-spring-bean创建的细节问题 三种创建Bean对象的方式 Bean的作用范围 Bean的生命周期 <?xml version="1.0" e ...

  7. 【Spring学习笔记 九】Spring声明式事务管理实现机制

    什么是事务?事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用,关乎数据准确性的地方我们一定要用到事务,防止业务逻辑出错. 什么是事务管理,事务管理对于企业应用而言至 ...

  8. Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习

    Spring Cloud学习笔记-网关Spring Cloud Gateway官网教程实操练习 1.Spring Cloud Gateway介绍 2.在Spring Tool Suite4或者IDEA ...

  9. Java学习笔记-Day64 Spring 框架(二)

    Java学习笔记-Day64 Spring 框架(二) 一.控制反转IOC和依赖注入DI 1.控制反转IOC 2.依赖注入DI 3.Spring IOC容器 3.1.简介 3.2.实现容器 3.2.获 ...

最新文章

  1. 机器学习成为未来趋势 北美未来将保持最大市场规模
  2. Elasticsearch索引定时清理
  3. torchvision0.2.2_速度全面碾压,PCIE4.0 M.2对撞PCIE3.0 M.2
  4. python入门经典书籍知乎_知乎问题回答 - 《Python100天从新手到大师》 - 开源书籍(oscbook.com)...
  5. Java设计模式:命令模式
  6. php 内置mail 包,PHP使用pear自带的mail类库发邮件的方法
  7. BZOJ 1012 - 树状数组+维护最大值 / 单调栈+二分 / 暴力(伪单调队列) / 线段树...
  8. MyBatis源码阅读(八) --- Executor执行器
  9. 模式识别和机器学习重点算法总结篇
  10. lammps教程:薄膜渗透过滤模拟--平衡弛豫过程
  11. Qt之QSS使用与基本语法
  12. 怎样破解QQ空间代码(转载)及最新收集2009年QQ空间皮肤代码大全 (http://www.enet.com.cn/article/2009/0812/A20090812519367.shtml)
  13. Iptables+Tproxy+RedSocks2的udp转发相关
  14. DeepFM算法详解-推荐算法中的皇冠
  15. 云大使成长精华指引(全)
  16. 解决WMI Provide Host占用CPU过高问题(win10亲测有用)
  17. 如何查找重复文件并快速删除,电脑查重复文件的方法
  18. RFID反向不归零编码(NRZ)
  19. NetworkX系列教程(2)-graph生成器
  20. Java8日期API

热门文章

  1. CLIP(Contrastive Language-Image Pre-Training)简介
  2. 大数据如何对大型设备进行故障预测及健康管理的?
  3. python自动办公:python便捷发邮件
  4. 全球气候:变冷还是变暖?
  5. 【node错误】npm ERRInvalid name:解决
  6. matlab meshgrid例子,科学网—matlab使用笔记-meshgrid函数的使用 - 骆佳良的博文
  7. 实训五 思科路由器端口的基本配置
  8. uniapp关于this.$refs.xxx获取组件出现undefined的解决方法
  9. 北京地铁,2号线换乘13号线,用时最短换乘线路
  10. 负载测试、压力测试和性能测试之间的联系和区别?