概述
很多时候,我们写的流程都嵌在一大堆代码中,没有办法直观的管理。而spring webflow可以将流程抽出来,放到一个单独的xml文件中,这样流程就不会埋没在代码里了。
今天要做一个很简单的流程: 商品发布流程
做出来后,大概就是下面这个样子:
“类别选择”页面:release_first.jsp
“商品信息填写”页面:release_second.jsp
项目的环境是 Spring MVC项目。
需要修改的文件:
- spring-servlet.xml (spring MVC配置文件)
- applicationContext.xml (spring 配置文件)
- releasegoods-flow.xml (spring webflow 配置文件)
- release_first.jsp
- release_second.jsp
实现
spring-servlet.xml
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry" />
</bean>
<!-- Define FlowHandlerAdapter to handle Spring Web Flow request call.
This is the Controller class in Spring Web Flow -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
FlowHandlerMapping : 这个类会告诉DispatcherServlet,将匹配的请求发送给webflow处理(也就是发给FlowHandlerAdapter),匹配规则定义在flowRegistry里。
FlowHandlerAdapter :起到流程控制器的作用,处理所有进入webflow的请求
上面两个配置,其实都是在解决请求怎么进入到流程的问题,并不属于流程的一部分。
applicationContext.xml
<!-- webflow相关配置 -->
<!-- 流程执行器 -->
<flow:flow-executor id="flowExecutor" flow-registry="flowRegistry"></flow:flow-executor>
<!-- 流程注册表 -->
<flow:flow-registry id="flowRegistry">
<flow:flow-location path="/WEB-INF/flows/releasegoods/releasegoods-flow.xml" id="viewgoodsclass"></flow:flow-location>
</flow:flow-registry>
<flow:flow-executor>
:流程执行器,负责创建和执行流程<flow:flow-registry
:流程注册表,通过<flow:flow-location>
的path属性指出流程定义的位置,通过id属性指出流程的访问地址。比如这里定义的流程,就可以通过:http://localhost:8080/viewgoodsclass 来打开。
releasegoods-flow.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">
<var name="goods" class="com.huanle.model.entity.GoodsEntity"/>
<view-state id="viewfirst" view="/views/user/releasegoods/release_first.jsp" model="goods">
<transition on="submit" to="viewsecond"></transition>
</view-state>
<view-state id="viewsecond" view="/views/user/releasegoods/release_second.jsp" model="goods">
<transition on="submit" to="returntouserindex"></transition>
</view-state>
<end-state id="returntouserindex" view="/index.jsp"></end-state>
<global-transitions>
<transition on="cancel" to="returntouserindex"></transition>
</global-transitions>
</flow>
上面这个文件定义了流程:
<var>
: 配置了一个变量,作用范围是整个流程,注意,这个变量的类要实现Serializable接口<view-state>
: 视图状态,流程在这个状态下会显示一个视图与用户交互。<transition>
: 定义跳转,比如这里的第一个transition标签的意思是:检测到submit事件就跳转到viewsecond状态。submit事件指的不是html form的submit事件,而是我们自定义的一个标记,可以随便取名。<end-state>
:终点状态。(也许会奇怪为什么没有开始状态,因为默认第一个状态就是开始状态)<global-transitions>
: 定义全局跳转,因为cancel在任何一个状态里都需要,所以配置为全局跳转。
release_first.jsp
<form:form action="${flowExecutionUrl}&_eventId=submit" method="post" commandName="goods">
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"/>
<div class="release"><input type="submit" value="我已阅读以下规则,现在发布宝贝"/></div>
</form:form>
- flowExecutionUrl :提交的url,通过这个地址可以和流程交互。一般就像上面这样用就可以了。
- _eventId : 这个参数就是我们自定义的事件,状态根据这个事件参数跳转到不同的下一状态。
- flowExecutionKey:这个隐藏域用来区分不同的流程实例,必须要加到表单中提交
release_second.jsp
跟release_first.jsp 类似。
就这样,一个流程定义好了,可以通过:http://localhost:8080/viewgoodsclass 来打开这个流程