Spring MVC Flash Attribute 的讲解与使用示例 已翻译 100%

0595 投递于 2014/04/05 07:47 (共 5 段, 翻译完成于 04-10)
阅读 23142
收藏 160
15
加载中

Spring MVC 3.1 version has added a very useful feature Flash attribute which it lacked and is now solving a long time problem of POST/Redirect/GET pattern.

In a normal Web based MVC application each form submitted POST the data to the server. A normal spring controller (tagged with annotation @Controller) fetches the data from request and process it further (save or update in database). Once the operation is successful, user is forwarded to page showing success of operation. Traditionally if we handle this via POST/Forward/GET, then it may cause sometime multiple form submission issue. User might press F5 and the same data is posted again.

To overcome this problem, POST/Redirect/GET pattern is used in MVC applcations. Once user form is posted successfully, we redirect the request to another success page. This causes browser to perform a new GET request and load the page. Thus is user presses F5, the GET request gets loaded instead of submitting form again.

POST/Redirect/GET
Image credit: Wikipedia

已有 1 人翻译此段
我来翻译

While this approach looks perfect and solve the problem of multiple form submission, it add one more issue of retrieving request parameters and attributes. Normally when we generate an http redirect request, the data stored in request is lost making it impossible for next GET request to access some of the useful information from request.

Flash attributes comes handy in such cases. Flash attributes provide a way for one request to store attributes intended for use in another. Flash attributes are saved temporarily (typically in the session) before the redirect to be made available to the request after the redirect and removed immediately.

spring-mvc-flash-map-manager

In order to do this, Flash feature uses two collections. FlashMap is used to hold flash attributes while FlashMapManager is used to store, retrieve, and manage FlashMap instances.

For each request an “input” flash map is created which stores flash attribute from any previous request and an “output” flash map is created which stores any subsequent attributes that we store in this request.

已有 1 人翻译此段
我来翻译

Usage

In order to use Flash attribute in your Spring MVC application make sure you using version 3.1 or above. Also add mvc:annotation-driven to spring-servlet.xml file.

<mvc:annotation-driven />

Once this is done, Flash attribute is automatically set “on” for usage. Just add attribute RedirectAttributes redirectAttributes to your Spring controller’s method.

import org.springframework.web.servlet.mvc.support.RedirectAttributes;
//...

	@RequestMapping(value="addcustomer", method=RequestMethod.POST)
	public String addCustomer(@ModelAttribute("customer") Customer customer,
			final RedirectAttributes redirectAttributes) {
	//...
		redirectAttributes.addFlashAttribute("message", "Successfully added..");
	//...

		return "redirect:some_other_request_name";
	}

The addFlashAttribute method automatically add the given parameter to the output flash map and pass it to the subsequent requests.

Let us see a complete demo application which uses Flash attribute to perform POST/Redirect/GET and passes some information.

Flash Attribute Example

The following application displays a form to user. Once the user inputs data and submits form, the page is redirected to another page where success message is displayed. On this new redirected page, the user input is displayed.

已有 1 人翻译此段
我来翻译

Step 1: Required JAR and Project Structure

If you using Maven as dependency management, use below dependencies to add Spring 3.1 MVC support.

	<dependencies>
		<!-- Spring 3.1 MVC  -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>3.1.2.RELEASE</version>
		</dependency>
		<!-- JSTL for c: tag -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	</dependencies>

Alternatively, you can also download following JAR files and place them under /WEB-INF/lib folder.

spring-mvc-flash-attribute-jar-files

Step 2: Spring Configuration

Add Spring support to web project by adding DispatcherServlet to web.xml.
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" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

	id="WebApp_ID" version="2.5">
	
	<display-name>Spring MVC Flash attribute example</display-name>
	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
    	<servlet-name>default</servlet-name>
    	<url-pattern>/index.html</url-pattern>
	</servlet-mapping>	
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>
</web-app>

Also the spring-servlet uses mvc:annotation-driven to enable mvc and also scans the project with context:component-scan tag.

spring-servlet.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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc  http://www.springframework.org/schema/mvc/spring-mvc.xsd">
		
	
	<bean id="jspViewResolver"
	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 name="suffix" value=".jsp" />
	 </bean>
	
	<context:component-scan base-package="net.viralpatel.controller" />
	<mvc:annotation-driven />
 
</beans>

Step 3: Spring Controller – RedirectAttributes

The Controller code uses Customer.java object as bean (command) to holds customer information.

Customer.java

package net.viralpatel.spring;

public class Customer {
	private String firstname;
	private String lastname;
	private int age;
	private String email;

	//getter, setter methods
}

The CustomerController class has 3 methods. Method showForm is mapped with /form URL and is used to display Add New Customer form. Th method addCustomer is mapped with URL /addcustomer and is used on POST request.

CustomerController.java

package net.viralpatel.controller;

import net.viralpatel.spring.Customer;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
public class CustomerController {

	
	
	@RequestMapping(value="showform", method=RequestMethod.GET)
	public String showForm(@ModelAttribute("customer") Customer customer) {
		return "add_customer";	
	}
	
	@RequestMapping(value="addcustomer", method=RequestMethod.POST)
	public String addCustomer(@ModelAttribute("customer") Customer customer,
			final RedirectAttributes redirectAttributes) {

		redirectAttributes.addFlashAttribute("customer", customer);
		redirectAttributes.addFlashAttribute("message","Added successfully.");

		return "redirect:showcustomer.html";	
	}

	
	@RequestMapping(value="showcustomer", method=RequestMethod.GET)
	public String showCustomer(@ModelAttribute("customer") Customer customer) {
		System.out.println("cust:" + customer.getFirstname());
		return "show_customer";
	}
}

Note how we used redirectAttributes parameter on method addCustomer to map flash attributes. Also we used addFlashAttribute method to set new parameters to flash attribute.

已有 1 人翻译此段
我来翻译

Step 4: Views

The add customer JSP displays Add New Customer form.
add_customer.jsp

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<body>
	<h1>Add New Customer</h1>
	<form:form action="addcustomer.html" method="post" commandName="customer">
	<table>
		<tr>
			<td><form:label path="firstname">Firstname</form:label></td>
			<td><form:input path="firstname" /> </td>
		</tr>
		<tr>
			<td><form:label path="lastname">Lastname</form:label></td>
			<td><form:input path="lastname" /> </td>
		</tr>
		<tr>
			<td><form:label path="age">Age</form:label></td>
			<td><form:input path="age" /> </td>
		</tr>
		<tr>
			<td><form:label path="email">Email</form:label>
			<td><form:input path="email" /> </td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" value="Add Customer" />
			</td>
		</tr>
	</table>
	</form:form>
</body>
</html>

Show customer JSP simply shows the customer’s first and last name and a success message set as flash attributes.

show_customer.jsp

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<body>
<h1>${message}</h1>
	${customer.lastname}, ${customer.firstname} added successfully..
</body>
</html>

Demo:

Execute the web project.
URL: http://localhost:8080/SpringMVC_Flash_Attribute_Maven_example/form.html
spring-mvc-flash-attribute-demo-form

spring-mvc-flash-attribute-demo-success

Download Source Code

SpringMVC_Flash_Attribute_example.zip (3.5 MB)

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(24)

qwfys
qwfys
不错
徐林
徐林

org.springframework.web.servlet.support.SessionFlashMapManager
如果系统没有配置,默认保持在Session中。

在单机部署中,这个没有问题;但在集群环境中,数据可能会串掉。

沉城
沉城

引用来自“小杨阿哥哥”的评论

压根就不用这种方式,重定向的话ModelAndView可以接受map,如果是redirectView也就将参数自动转换到URL中

引用来自“xmut”的评论

什么叫“压根”,佩服啊! 先不说是否加密之类的东西,凭什么我们要跟你一样都把参数都放在URL中!

没错,有些人就是比较自以为是

XzhiF
XzhiF

james_you
james_you

提交后,点击浏览器返回后,再提交呢? 一般这种事情,都是用token做嘛

pauli
pauli

里面好东西不少了 https://code.google.com/p/viralpatel-net-tutorials/downloads/list

vio
vio

个人认为用cookies比session存储这些数据好一点

leon_lau
leon_lau

源码
synchronized (writeLock) {
      List<FlashMap> allMaps = retrieveFlashMaps(request);
      allMaps = (allMaps == null) ? new CopyOnWriteArrayList<FlashMap>() : allMaps;
      allMaps.add(flashMap);
      updateFlashMaps(allMaps, request, response);
    }


/**
   * Save the given FlashMap instance, if not empty, in the HTTP session.
   */
  protected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response) {
    request.getSession().setAttribute(FLASH_MAPS_SESSION_ATTRIBUTE, flashMaps);
  }

unnamed
unnamed

spring mvc 也加了flash 啊。。

X
Xiao_f

如果存入session redirect后即删除,再刷新不就找不到了,感觉放到url中才是解决之道

返回顶部
顶部