使用Spring Web Flow--学习一个简单例子

燕智
2023-12-01

概述:

Spring 的工作流就是类似网上购物,注册用户-》选择商品-》添加到购物车-》付款-》收货-》售后,一套已经固化的流程。

学习博文地址:

http://blog.csdn.net/hejingyuan6/article/details/46723021 写到非常好,大家可以跟着学习一下

看一下工程结构:

操作步骤:

step1、引入spring web flow jar 当前还要普通Spring相关jar包

<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.4.5.RELEASE</version>
</dependency>

step2、配置运行环境

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>webflow</display-name>
  <servlet>
  	<servlet-name>webServlet</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:spring-mvc.xml</param-value>
  	</init-param>
  	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>webServlet</servlet-name>
  	<url-pattern>/spring/*</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

配置集合Springmvc+flow配置文件

<?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:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
    http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
 	<context:component-scan base-package="com.jack"/>
 	<!-- 启动配置注解 -->
 	<context:annotation-config/>
 	<import resource="webmvc.xml"/>
 	<import resource="webflow.xml"/>
 </beans>

配置Springmvc

<?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:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
    http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
 	
 	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
 		<property name="prefix" value="/WEB-INF/jsp/"></property>
 		<property name="suffix" value=".jsp"/>
 	</bean>
 	
 	<!-- SimpleUrlHandlerMapping 通过配置文件,把一个URL映射到Controller -->
 	<bean id="viewMappings" 
 		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 		<property name="mappings">
 			<value>/shopping.do=flowController</value>
 		</property>
 		<property name="defaultHandler">
 			<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
 		</property>
 	</bean>
 	<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
 		<property name="flowExecutor" ref="flowExecutor"/>
 	</bean>
 </beans>

总结:

1、首先配置jsp通用的视图解析器viewResolver

2、SimpleUrlHandlerMapping 可以将map与控制器类关联,格式类似: path = 控制器。例如上 /shopping.do = flowController(flowController 也就是工作流的入口)

3、UrlFilenameViewController功能类似InternalResourceViewResolver,它将URL解释成视图例如:"/index.html" -> "index" 

4、FlowController类似董事长(BP) 而下属flowExecutor 类似首席执行官(CEO),老大不需要自己亲自去弄,叫ceo传达一下就行
 

配置flow (为首席执行官配置资源和任务)

<?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:context="http://www.springframework.org/schema/context"  
    xmlns:webflow="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/context   
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/webflow-config
    http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">  
 	
 	<webflow:flow-executor id="flowExecutor"/>
 	
 	<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
 		<webflow:flow-location path="classpath:shopping.xml" id="shopping"/>
 		<webflow:flow-location path="classpath:addToCart.xml" id="addToCart"></webflow:flow-location>
 	</webflow:flow-registry>
 	
 	<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"/>
 	<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
 		<property name="viewResolvers" ref="viewResolver"/>
 	</bean>
 </beans>


总结:

1、webflow:flow-executor 就是默认首席执行官

2、分配的任务就是shopping.xml和addToCart.xml

3、工作流中需要渲染工作,这时候服务工作就交给了viewResolver

step3、配置工作流

欢迎页-》挑选商品-》加入购物-》计算总数量和总价格

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/spring-webflow-2.0.xsd">  
 	
 	  <var name="mycart" class="com.jack.Cart"/>
 	  <on-start>
 	  	<set name="conversationScope.cart" value="mycart"/>
 	  </on-start>
 	  <view-state id="viewCart" view="viewCart"> 
 	  	<on-render>
 	  		<evaluate expression="productService.getProducts()" result="viewScope.products"/>
 	  	</on-render> 
        <transition on="submit" to="viewOrder">  
        </transition>  
        <transition on="addToCart" to="addProductToCart"></transition>
    </view-state>  
    <subflow-state id="addProductToCart" subflow="addToCart">
    	<transition on="productAdded" to="viewCart"/>
    </subflow-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>


 

addToCart.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">  
 	
    <on-start>  
        <set name="requestScope.productId" value="requestParameters.productId" />  
    </on-start>  
    
    <action-state id="addToCart">
    	<evaluate expression="cart.addItem(productService.getProduct(productId))"></evaluate>
    	<transition to="productAdded"/>
    </action-state>
    <end-state id="productAdded"/>
 </flow>


 

总结:

1、<var>表示定义变量,Cart就是购物车,就像你去超市购物,在入口推着购物车,每人一个

2、<on-start>表示开始时候准备好,conversationScope.cart (表示作用域,简单就是在整个一次购物中,这个购物车只会你使用)

3、<view-state>表示jsp显示的时候,告诉需要显示的view=“viewCart” 表示为viewCart.jsp

4、<on-render>表示在显示jsp的时候需要做一些事情,比如装置一些数据,类似在进商场之前,工作人员已经将货物上架,不然你买啥

5、<transition>表示接下一个步骤,类似你看到喜欢商品,需要做的一个动作就是将商品放入购物车,这里有两种情况,加入购物车还是不加入

6、不加入就去前台结账,如果加,这是需要增加加的动作,这里它增加一个字流程<subflow-state> 注意属性subflow="addToCart"

7、你会发现addToCart在shopping.xml,它在addToCart.xml, 注意它标签是<action-state>而不是<view-state> 它是一个动作而不是展示视图

8、添加完商品转到了productAdded,也就是shopping.xml这里来了,发现它又转到viewCart,它要更新商品数量和类型

9、假如,我们已经添加好了商品,点击submit, 它转到viewOrder,viewOrder展示你已经选择的商品

10、点击confirm表示你确认你购买的商品

11、最后重定向到externalRedirect:servletRelative:/index.jsp ,也就是首页

12、注意addToCart.xml定义requestScope.productId (表示在请求作用域中设置一个属性为productId ,它的值取自requestParameters.productId[本身请求的过来的数据])

13、xml如何实现java代码,使用SpEL ,也就是Spring Expression Language,例如expression="cart.addItem(productService.getProduct(productId))" 

总的来说就是它用xml画了一个流程图

步骤4、jsp文件

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>Hello!</h1>
	<br>
	<a href="shopping.do">ViewCart</a>
</body>
</html>



orderConfirmed.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>Order Confirmed</h1>
	<br>
	<a href="${flowExecutionUrl }&_evenId=returnToIndex">Return to index</a>
</body>
</html>


viewCart.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>  
    <h1>View Cart</h1>  
     <h2>Items in Your Cart</h2>
   <c:choose>
   	<c:when test="${empty cart.items}">
   		<p>Your cart is empty.</p>
   	</c:when>
   	<c:otherwise>
   		<table border="1" cellspacing="0">
   			<tr>
   				<th>Item</th>
   				<th>Quantity</th>
   				<th>Unit Price</th>
   				<th>Total</th>
   			</tr>
   			<c:forEach var="item" items="${cart.items }">
   				<tr>
   					<td>${item.product.descript }</td>
   					<td>${item.quantity }</td>
   					<td>${item.product.price }</td>
   					<td>${item.totalPrice }</td>
   				</tr>
   			</c:forEach>
   			<tr>
   				<td>Total:</td>
   				<td></td>
   				<td></td>
   				<td>${cart.totalPrice }</td>
   			</tr>
   		</table>
   	</c:otherwise>
   </c:choose>
    <a href="${flowExecutionUrl}&_eventId=submit">Submit</a>  
    <h2>Products for Your Choice</h2>
    <table>
    	<c:forEach var="product" items="${products}">
    		<tr>
    			<td>${product.descript }</td>
    			<td>${product.price }</td>
    			<td><a href="${flowExecutionUrl}&_eventId=addToCart&productId=${product.id}">[add  
                        to cart]</a></td>
    		</tr>
    	</c:forEach>
    </table>
</body>
</html>


viewOrder.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>  
    <h1>Order</h1>
    <c:choose>
    	<c:when test="${empty cart.items }">
    		<p>Your cart is empty.</p>
    	</c:when>
    	<c:otherwise>
    		<table border="1" cellspacing="0">
    			<tr>
    				<th>Item</th>
    				<th>Quantity</th>
    				<th>Unit Price</th>
    				<th>Total</th>
    			</tr>
    			<c:forEach var="item" items="${cart.items }">
    				<tr>
    					<td>${item.product.descript }</td>
    					<td>${item.quantity }</td>
    					<td>${item.product.price }</td>
    					<td>${item.totalPrice }</td>
    				</tr>
    			</c:forEach>
    			<tr>
    				<td>TOTAL:</td>
    				<td></td>
    				<td></td>
    				<td>${cart.totalPrice }</td>
    			</tr>
    		</table>
    	</c:otherwise>
    </c:choose>  
    <a href="${flowExecutionUrl}&_eventId=confirm">Confirm</a>  
  
</body>  
</html>


总结:

1、flowExecutionUrl跳转处理控制器

2、_eventId 表示事件Id

java类:

Cart.java

package com.jack;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Cart implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 2218144992574949101L;
	
	private Map<Integer, CartItem> map = new HashMap<Integer, CartItem>();
	
	public List<CartItem> getItems(){
		return new ArrayList<CartItem>(map.values());
	}
	
	//addItem 用于向购物车添加商品、
	public void addItem(Product product){
		int id=product.getId();
		CartItem item = map.get(id);
		if(item != null){
			item.increaseQuantity();
		}else{
			map.put(id, new CartItem(product,1));
		}
	}
	public int getTotalPrice(){
		int total =0;
		for (CartItem item : map.values()){
			total += item.getProduct().getPrice() * item.getQuantity();
		
		}
		return total;
	}

}


CartItem.java

package com.jack;

import java.io.Serializable;

public class CartItem implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 7087013311725981757L;
	
	private Product product;//商品
	private int quantity; //数量
	public CartItem(Product product, int quantity) {
		super();
		this.product = product;
		this.quantity = quantity;
	}
	//计算该条目的总价格
	public int getTotalPrice(){
		return this.quantity*this.product.getPrice();
	}
	
	//增加商品的数量
	public void increaseQuantity(){
		this.quantity++;
	}
	public Product getProduct() {
		return product;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setProduct(Product product) {
		this.product = product;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
	
	


}


Product.java

package com.jack;

import java.io.Serializable;

public class Product implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -3547488052308853185L;
	private int id;
	private String descript;
	private int price;
	
	
	public Product() {
		super();
		// TODO Auto-generated constructor stub
	}


	public Product(int id, String descript, int price) {
		super();
		this.id = id;
		this.descript = descript;
		this.price = price;
	}


	public int getId() {
		return id;
	}


	public String getDescript() {
		return descript;
	}


	public int getPrice() {
		return price;
	}


	public void setId(int id) {
		this.id = id;
	}


	public void setDescript(String descript) {
		this.descript = descript;
	}


	public void setPrice(int price) {
		this.price = price;
	}


	
	
	
}


ProductService.java

package com.jack;

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(1, "Chihuahua", 1000));
		products.put(3, new Product(1, "Labrador", 1000));
	}

	public List<Product> getProducts() {
		return new ArrayList<Product>(products.values());
	}

	public void setProducts(Map<Integer, Product> products) {
		this.products = products;
	}
	
	
	public Product getProduct(int productId){
		return products.get(productId);
	}
}
 类似资料: