订购披萨的应用整体比较比较复杂,现拿出其中一个简化版的流程:即用户访问首页,然后输入电话号(假定未注册)后跳转到注册页面,注册完成后跳转到配送区域检查页面,最后再跳转回首页。通过这个简单的Demo用来说明Spring Web Flow的具体工作流程,方便以后细化整个订购披萨应用。
基于Maven的项目,目录结构如下:
1.首先建立依赖,pom.xml文件
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 <groupId>com.li</groupId> 5 <artifactId>SpringWebFlow</artifactId> 6 <packaging>war</packaging> 7 <version>0.0.1-SNAPSHOT</version> 8 <name>SpringWebFlow Maven Webapp</name> 9 <url>http://maven.apache.org</url> 10 <dependencies> 11 <dependency> 12 <groupId>junit</groupId> 13 <artifactId>junit</artifactId> 14 <version>3.8.1</version> 15 <scope>test</scope> 16 </dependency> 17 <!--SpringMVC所需要的依赖 --> 18 <dependency> 19 <groupId>org.springframework</groupId> 20 <artifactId>spring-beans</artifactId> 21 <version>4.3.7.RELEASE</version> 22 </dependency> 23 24 <dependency> 25 <groupId>org.springframework</groupId> 26 <artifactId>spring-context</artifactId> 27 <version>4.3.7.RELEASE</version> 28 </dependency> 29 30 <dependency> 31 <groupId>org.springframework</groupId> 32 <artifactId>spring-core</artifactId> 33 <version>4.3.7.RELEASE</version> 34 </dependency> 35 36 <dependency> 37 <groupId>org.springframework</groupId> 38 <artifactId>spring-web</artifactId> 39 <version>4.3.7.RELEASE</version> 40 </dependency> 41 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-webmvc</artifactId> 45 <version>4.3.7.RELEASE</version> 46 </dependency> 47 48 <dependency> 49 <groupId>org.springframework</groupId> 50 <artifactId>spring-expression</artifactId> 51 <version>4.3.7.RELEASE</version> 52 </dependency> 53 <!--Spring Web Flow所需要的依赖 --> 54 <dependency> 55 <groupId>org.springframework.webflow</groupId> 56 <artifactId>spring-binding</artifactId> 57 <version>2.4.4.RELEASE</version> 58 </dependency> 59 60 <dependency> 61 <groupId>org.springframework.webflow</groupId> 62 <artifactId>spring-faces</artifactId> 63 <version>2.4.4.RELEASE</version> 64 </dependency> 65 66 <dependency> 67 <groupId>org.springframework.webflow</groupId> 68 <artifactId>spring-js</artifactId> 69 <version>2.4.4.RELEASE</version> 70 </dependency> 71 72 <dependency> 73 <groupId>org.springframework.webflow</groupId> 74 <artifactId>spring-js-resources</artifactId> 75 <version>2.4.4.RELEASE</version> 76 </dependency> 77 78 <dependency> 79 <groupId>org.springframework.webflow</groupId> 80 <artifactId>spring-webflow</artifactId> 81 <version>2.4.4.RELEASE</version> 82 </dependency> 83 84 <dependency> 85 <groupId>javax.servlet</groupId> 86 <artifactId>servlet-api</artifactId> 87 <version>2.5</version> 88 </dependency> 89 90 <dependency> 91 <groupId>javax.servlet</groupId> 92 <artifactId>jstl</artifactId> 93 <version>1.2</version> 94 </dependency> 95 </dependencies> 96 <build> 97 <finalName>SpringWebFlow</finalName> 98 <plugins> 99 <plugin> 100 <groupId>org.apache.maven.plugins</groupId> 101 <artifactId>maven-war-plugin</artifactId> 102 <version>3.0.0</version> 103 </plugin> 104 </plugins> 105 </build> 106 </project>
2.Spring Web Flow配置文件spring-wf.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:webflow="http://www.springframework.org/schema/webflow-config" 4 xsi:schemaLocation=" http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 6 http://www.springframework.org/schema/webflow-config 7 http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd"> 8 9 <!-- 流程注册器 隐含一句 flow-registry="flowRegistry" 10 默认表示引用bean id为 'flowRegistry'的流程注册表--> 11 <webflow:flow-executor id="flowExecutor" /> 12 13 <!-- 流程注册表 --> 14 <webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices"> 15 <!-- <webflow:flow-location path="/WEB-INF/flows/hello.xml" id="hello" />--> 16 <webflow:flow-location path="/WEB-INF/customer/customer-flow.xml" id="customer" /> 17 </webflow:flow-registry> 18 19 <!-- WebFlow 视图解析器 --> 20 <bean id="flowViewResolver" 21 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 22 <property name="viewClass" 23 value="org.springframework.web.servlet.view.JstlView"> 24 </property> 25 <property name="prefix" value="/WEB-INF/customer/"> 26 </property> 27 <property name="suffix" value=".jsp"> 28 </property> 29 </bean> 30 31 <!-- WebFlow 视图工厂构建服务 --> 32 <webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator" /> 33 34 <!-- WebFlow 视图工厂创建器,表示使用视图解析器将流程配置(xml)中的逻辑视图交给视图解析器解析 → jsp --> 35 <bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"> 36 <property name="viewResolvers" ref="flowViewResolver" /> 37 </bean> 38 39 <!-- 配置WebFlow 处理器映射器--> 40 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 41 <property name="mappings"> 42 <props> 43 <!-- 这个逻辑视图名的 前缀 必须与流程注册表中的 44 webflow:flow-location 的 id一致, 45 而 后缀 必须是当前DispatcherServlet匹配的地址,也就是 46 必须以.flow结束,否则不被前端控制器处理(视图名必须匹配*.flow) 47 --> 48 <!-- 这里代表将请求路径为hello.flow的url交给flowController处理 --> 49 <prop key="customer.flow">flowController</prop> 50 </props> 51 </property> 52 </bean> 53 54 <!--WebFlow 处理器,根据逻辑视图名到流程执行器中找到对应的注册表,进而找到流程配置文件,转到不同的物理视图--> 55 <!--主要工作就是负责将url转化成逻辑视图交给视图解析器解析 → jsp--> 56 <bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController"> 57 <property name="flowExecutor" ref="flowExecutor" /> 58 </bean> 59 </beans>
3.web.xml文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://xmlns.jcp.org/xml/ns/javaee" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 5 id="WebApp_ID" version="3.1"> 6 <servlet> 7 <servlet-name>FlowServlet</servlet-name> 8 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 9 <init-param> 10 <param-name>contextConfigLocation</param-name> 11 <param-value> 12 classpath:spring-wf.xml 13 </param-value> 14 </init-param> 15 <load-on-startup>1</load-on-startup> 16 </servlet> 17 <servlet-mapping> 18 <servlet-name>FlowServlet</servlet-name> 19 <url-pattern>*.flow</url-pattern> 20 </servlet-mapping> 21 </web-app>
4.流程注册文件,customer-flow.xml
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 8 9 <!-- Customer --> 10 <view-state id="welcome"> 11 <transition on="phoneEntered" to="registrationForm"/> 12 <transition on="cancel" to="cancel"/> 13 </view-state> 14 15 <view-state id="registrationForm"> 16 <transition on="submit" to="deliveryWarning" /> 17 <transition on="cancel" to="cancel" /> 18 </view-state> 19 20 21 <view-state id="deliveryWarning"> 22 <transition on="accept" to="success" /> 23 <transition on="cancel" to="cancel" /> 24 </view-state> 25 26 <view-state id="success"> 27 <transition on="back" to="cancel"></transition> 28 </view-state> 29 30 <!-- End state --> 31 32 <end-state id="cancel" view="externalRedirect:index.jsp"/> 33 <end-state id="customerReady" /> 34 </flow>
5.index.jsp(首页)
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 5 %> 6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 8 <html> 9 <head> 10 <base href="<%=basePath%>"> 11 12 <title>My JSP 'cart.jsp' starting page</title> 13 14 <meta http-equiv="pragma" content="no-cache"> 15 <meta http-equiv="cache-control" content="no-cache"> 16 <meta http-equiv="expires" content="0"> 17 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 18 <meta http-equiv="description" content="This is my page"> 19 <!-- 20 <link rel="stylesheet" type="text/css" href="styles.css"> 21 --> 22 23 </head> 24 25 <body> 26 <h2 align="center">Hello,WebFlow</h2><br/> 27 Spizza:<a href="customer.flow">进入Spizza应用</a><br/> 28 </body> 29 </html>
6.welcome.jsp(输入电话的页面)
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 3 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> 4 <% 5 String path = request.getContextPath(); 6 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 7 %> 8 9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 10 <html> 11 <head> 12 <base href="<%=basePath%>"> 13 14 <title>My JSP 'welcome.jsp' starting page</title> 15 16 <meta http-equiv="pragma" content="no-cache"> 17 <meta http-equiv="cache-control" content="no-cache"> 18 <meta http-equiv="expires" content="0"> 19 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 20 <meta http-equiv="description" content="This is my page"> 21 <!-- 22 <link rel="stylesheet" type="text/css" href="styles.css"> 23 --> 24 25 </head> 26 27 <body> 28 <h2>Welcome to Spizza!!!</h2> 29 <form:form> 30 <!-- 流程执行的key --> 31 <input type="hidden" name="_flowExecutionKey" 32 value="${flowExecutionKey}" /> 33 34 <input type="text" name="phoneNumber" /> 35 <br /> 36 <!-- 触发phoneEntered事件 --> 37 <a href="${flowExecutionUrl}&_eventId=phoneEntered">Lookup 38 Customer</a> 39 40 <a href="${flowExecutionUrl}&_eventId=cancel">Cancel</a> 41 <br /> 42 </form:form> 43 </body> 44 </html>
7.registrationForm.jsp(注册界面)
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 3 <html> 4 5 <head><title>Spring Pizza</title></head> 6 7 <body> 8 <h2>Customer Registration</h2> 9 <form> 10 <input type="hidden" name="_flowExecutionKey" 11 value="${flowExecutionKey}"/> 12 <b>Phone number: </b><input type='text'><br/> 13 <b>Name: </b><input type='text'><br/> 14 <b>Address: </b><input type='text'><br/> 15 <b>City: </b><input type='text'><br/> 16 <b>State: </b><input type='text'><br/> 17 <b>Zip Code: </b><input type='text'><br/> 18 </form> 19 <a href="${flowExecutionUrl}&_eventId=submit">Submit</a> 20 21 <a href="${flowExecutionUrl}&_eventId=cancel">Cancel</a> 22 </body> 23 </html>
8.deliveryWarning.jsp(配送区域检查页面)
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <html> 3 <head><title>Spring Pizza</title></head> 4 5 <body> 6 <h2>Delivery Unavailable</h2> 7 8 <p>The address is outside of our delivery area. The order 9 may still be taken for carry-out.</p> 10 11 <a href="${flowExecutionUrl}&_eventId=accept">Accept</a> | 12 <a href="${flowExecutionUrl}&_eventId=cancel">Cancel</a> 13 </body> 14 </html>
9.success.jsp(用户添加成功页面)
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 5 %> 6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 8 <html> 9 <head> 10 <base href="<%=basePath%>"> 11 12 <title>My JSP 'success.jsp' starting page</title> 13 14 <meta http-equiv="pragma" content="no-cache"> 15 <meta http-equiv="cache-control" content="no-cache"> 16 <meta http-equiv="expires" content="0"> 17 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 18 <meta http-equiv="description" content="This is my page"> 19 <!-- 20 <link rel="stylesheet" type="text/css" href="styles.css"> 21 --> 22 23 </head> 24 25 <body> 26 <h1>用户注册成功</h1> 27 <a href="${flowExecutionUrl}&_eventId=back">Home</a> | 28 </body> 29 </html>
9.运行结果
10.总结
相同点:SpringMVC和Spring Web Flow都实现了mvc设计模式
不同点:在mvc设计模式的实现方面不同
SpringMVC通过编写controller,service类来实现
而流程则通过bean来实现,底层已经帮你实现了,帮你来处理请求跳转到对应的视图界面