简介
在spring mvc中有些交互的场景中,我们需要将一些提交的内容在多个请求中可以进行传递。这种传递不仅仅是一些简单的参数,有时候希望是一些对象的传递。于是这就牵涉到一个多个请求中参数传递的问题。我们都知道,http请求它本身是无状态的,在一个请求场景中构造的参数到下一个请求中就已经丢失了。那么该怎么来实现参数传递呢?总的来说,有3种办法,一种是通过session的方式,因为相当于将需要传递数据缓存到服务器上,所以对于多个后续的请求都可以访问。一种是通过url template的方式,还有一种就是通过flash attribute。在本文中我们重点讨论一下url template和flash attribute这两种方式。
url template
url template的方式其实比较简单,它主要就是通过在提交表单之后指定后续跳转路径的参数来达到。比如如下的项目。
首先我们定义领域对象模型:
package com.springinpractice.ch03.model; public class Member { private String firstName; private String lastName; public Member() {} public Member(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String toString() { return firstName + " " + lastName; } }
然后定义一个提交表单的页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <!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>Nominee a member for the award</title> </head> <body> <h1>Nominee a member for the award</h1> <form:form modelAttribute="nominee"> <div>First name: <form:input path="firstName"/></div> <div>Last name: <form:input path="lastName"/></div> <div><input type="submit" value="Submit"></div> </form:form> </body> </html>
这两个部分的内容比较简单,重点是处理请求的controller部分:
@Controller public class NomineeController { private static final Logger logger = LogManager.getLogger(NomineeController.class); @RequestMapping(value = "/form", method = RequestMethod.GET) public String form(@ModelAttribute("nominee") Member member) { return "form"; } @RequestMapping(value = "/form", method = RequestMethod.POST) public String processFormData(@ModelAttribute("nomiee") Member member, Model model) { logger.info("Processing nominee: " + member); Map<String, Object> map = model.asMap(); logger.info("model[member]=" + map.get("member")); logger.info("model[nominee]=" + map.get("nominee")); model.addAttribute("firstName", member.getFirstName()); return "redirect:/members/{firstName}"; } @RequestMapping(value = "/members/{firstName}") public String displayMember(@PathVariable String firstName, Model model) { logger.info("firstName: " + firstName); model.addAttribute("firstName", firstName); return "member"; } }
在上述代码中,form方法用来展示提交表单的页面。重点在processForm方法中。我们定义了Model类型的参数并在其中定义了一个attribute "firstName"。完成设置之后然后跳转到页面/members/{firstName}。和普通的直接返回一个字符串不一样,这里因为定义了可以通过model的方式传递参数到jsp页面,它通过一种参数绑定解析的方式来解析参数firstName。这种方式还要一个好处,就是避免里面夹杂进一些非法的参数。
在后面的跳转处理方法中,也就是displayMember方法中,我们可以获取传递的参数,记录到日志中并在后面的页面中显示。
这个时候如果启动服务器,进入页面http://localhost:8080/FirstSpringWeb/form,我们将看到如下的内容:
在添加好必要的表单数据之后点击提交,页面将显示如下的内容:
这样,这种传递的方式效果就达到了。总结起来,它无非就是通过在前面提交表单的时候设定好后面跳转的页面是参数化的。比如我前面的跳转页面路径里设置{firstName}为frank,则后面跳转的页面则为http://localhost:8080/FirstSpringWeb/members/frank 。这相当于一种很简单的页面参数传递。
flash attribute
上面的那种方式只是简单的传递了一个url的参数,在一些情况下还是可以的。但是如果我们需要传递整个对象呢?前面的这种方式就不可行了。我们需要用到另外一个东西。那就是RedirectAttributes,这个对象可以用于请求之间参数的传递。我们对前面的示例做一个如下的修改:
@RequestMapping(value = "/form", method = RequestMethod.POST) public String processFormData(@ModelAttribute("nomiee") Member member, RedirectAttributes model) { logger.info("Processing nominee: " + member); Map<String, Object> map = model.asMap(); logger.info("model[member]=" + map.get("member")); logger.info("model[nominee]=" + map.get("nominee")); model.addFlashAttribute("member", member); return "redirect:/thanks"; } @RequestMapping(value = "/thanks", method = RequestMethod.GET) public String thanks() { return "thanks"; }
和前面的表单处理方式不一样,这里方法签名里的参数由Model改为RedirectAttributes,而且由原来model方法里的addAttribute改为addFlashAttribute。后面跳转之后显示页面的方法则看起来很简单,就是一个直接显示页面的代码。
我们再来看显示的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>Thanks</title> </head> <body> <h1>Thanks</h1> <p>Thanks for nominating ${member}.</p> </body> </html>
这里比较有意思的地方是我们可以显示了一个参数${member}。如果我们尝试一下在页面中去显示一个并不存在的参数,页面会显示空白的内容,在这里会怎么样呢?
我们启动页面,输入如下参数:
提交后我们将看到如下的内容:
为什么上面的内容可以被传递呢?这个RedirectAttributes又不是会施魔法,肯定有什么办法来传递。其实这里传递的方式本质上还是用到了session,不过这种方式只是临时借用了一下session。它在每次发生第一个请求的时候,也就是当我们刚提交表单的时候,会将我们设定的参数放到session中。在下一个请求,也就是我们跳转到后面的那个显示内容的请求时,它会从session里来取我们保存的内容。像这里就是因为保存了member这个对象,而且它对应的参数名是"member",所以在后面的显示页面里就有内容。但是在这个请求结束后,它们又会将我们在session里保存的内容给去掉。
所以说,上述的办法只是对一种使用session临时存放数据的方法的封装,让我们用起来简单一点而已。对于上述两个示例的详细实现可以参照后面附件里的内容。
总结
在一些请求之间传递参数的方法有若干种,主要是通过session, url template, redirect attribute等。其实它们本质上无非就是要将一个请求里的消息传递给下一个请求。所以要么就是用简单的将参数放到请求路径里,要么就是将数据放到某个存储的地方,让后面的请求去读取。也没什么特别的。
相关推荐
**Spring MVC 学习笔记** Spring MVC 是 Spring 框架的一个模块,专门用于构建 Web 应用程序。它提供了一种模型-视图-控制器(Model...在学习过程中,阅读源码、参考官方文档以及查阅社区资源都是提升技能的有效途径。
在传统的 Servlet 和 JSP 结合的开发模式中,请求首先到达 Servlet,Servlet 处理业务逻辑,然后设置 Model,接着通过 Forward 或 Redirect 将控制权交给 JSP,JSP 负责渲染视图并返回给客户端。Spring MVC 在此基础...
在 Spring MVC 中,数据跳转主要指的是控制器(Controller)处理完请求后,将数据转发到视图(View)进行展示的过程。这里的“跳转”实际上是指请求处理后的视图重定向或转发。 #### 转发与重定向 - **转发(forward)**...
- **POST**:向指定资源提交数据进行处理请求(例如提交表单或者上传文件),数据被包含在请求体中。 - **PUT**:替换目标的当前内容。 - **DELETE**:删除指定的页面。 - **HEAD**:类似于 GET 请求,只不过...
在这个实例中,我们将重点讨论如何使用Spring MVC的注解进行数据的增删改操作,并结合Hibernate作为ORM(对象关系映射)工具。 首先,`@Controller`注解标记了一个类作为Spring MVC的控制器,负责处理HTTP请求。在...
在Spring MVC 3的基础实践中,配置是至关重要的第一步。要启用Spring MVC,首先需要在`web.xml`中进行相应的配置。以下是一些关键步骤: 1. **Servlet Dispatcher配置**: - 首先,定义一个`DispatcherServlet`,...
在Spring MVC框架中,`@RequestMapping`注解是核心组件之一,它用于处理HTTP请求映射,使得控制器类(Controller)中的方法能够与特定的URL路径关联起来。本篇文章将深入探讨`@RequestMapping`的使用、功能以及相关...
在Spring MVC中,文件的上传和下载是常见的功能需求,这涉及到客户端与服务器之间的数据传输。本篇文章将深入探讨Spring MVC如何实现文件上传和下载。 ### 文件上传 1. **依赖配置**:在Spring MVC项目中,为了...
在 Spring MVC 中,可以通过 `Model` 或 `ModelMap` 对象向视图传递数据。这些数据可以在视图层展示或用于生成动态内容。例如: ```java @RequestMapping(value = "/details") public String details(Model model) ...
- **重定向**:在控制器方法中返回“redirect:/url”。 #### 十三、处理Ajax请求 Spring MVC 提供了多种方式来处理Ajax请求,包括使用`@ResponseBody`注解直接返回JSON或XML格式的数据。 #### 十四、多视图控制器...
在 Spring MVC 中,注解扮演着非常重要的角色,它们使得代码更加简洁、易读,并减少了 XML 配置。下面将详细讲解 Spring MVC 中常用的注解。 1. `@Controller`:这个注解标记一个类作为 Spring MVC 的控制器。控制...
这里的`redirect:/users`就是一个`mvcURL`,它不仅触发了重定向,还将`successMessage`属性添加到了模型中,以便在目标页面上显示。 总的来说,`mvcURL`是Spring MVC中构建Web应用的重要概念,它涵盖了请求处理、...
在Spring MVC中,可以通过实现`HandlerInterceptor`接口或继承`HandlerInterceptorAdapter`类来创建拦截器。 ```java public class MyInterceptor implements HandlerInterceptor { @Override public boolean ...
当`@ModelAttribute`注解在控制器方法的参数上时,Spring MVC会尝试从请求中获取对应的数据,并将其转换为该参数类型的对象。这个过程包括以下步骤: - **查找数据源**:Spring MVC会检查请求参数、模型属性...
Spring MVC提供了一种特殊的属性类型——Flash属性,可以在重定向过程中传输数据,但只在下一个请求中有效,之后会被自动清除。这种方式可以避免内存泄漏的风险: ```java @RequestMapping(method = RequestMethod....
在本文中,我们将深入探讨基于注解的Spring MVC在实现增删改操作中的应用。Spring MVC是Spring框架的一部分,主要用于构建Web应用程序。它利用注解简化了开发过程,使得开发者无需编写大量的XML配置文件,就能实现...
除了上述的注解,Spring MVC还有许多其他注解,如`@SessionAttributes`用于在session中存储模型数据,`@ExceptionHandler`用于全局异常处理,`@InitBinder`用于初始化数据绑定行为,等等。这些注解共同构建了一个...