Spring MVC 重定向传递数据

1. 前言

本节课程和大家一起讲解 Spring MVC 框架是如何跨请求传递数据的,让数据在重定向期间能被读出来。你需要重点掌握对 RedirectAttributes 组件的使用。

2. 查询字符串

如果是转发,数据模型只需要是请求作用域级别的,视图解析器便能从数据模型中拿到所需要的数据。对于重定向,因为跨了请求,视图无法读出请求作用域级别的数据模型中的数据。

如果要让数据模型中的数据被视图识别出来,则需要提升数据模型的作用域,如升级为会话作用域级别。所谓会话作用域,意味着数据会存放在服务器的会话缓存区。如果数据使用的频率不是很高,会产生空间上的浪费。

有没有一种较佳的方案,即不浪费服务器空间,又能传递数据了?

答案是肯定的。最原始的方式便是采用查询字符串的方式。

如下面的实例:

@RequestMapping("/response03")  
public String response03(ModelMap model) throws IOException {  
 // 发送给客户端的响应数据  
 String hello = "Hello";  
 model.addAttribute("data", hello);  
 return "redirect:/hello.jsp";  
}

model 中的数据只是请求作用域级别,重定向后的 hello.jsp 中无法获取此数据, Spring MVC 内部处理方式是把数据附加在 hello.jsp 后面。

打开浏览器,输入请求 http://localhost:8888/sm-demo/response03 地址,查看浏览器的地址栏中的 URL 变成 http://localhost:8888/sm-demo/hello.jsp?data=Hello

Tips:数据附加在 URL 后面是 Spring MVC 自动完成的。

图片描述

hello.jsp 页面中的数据读取方式改成下面的方式(从查询参数中读取)。

<div style="color:red">${param.data} </div> 

这种方式有 2 个缺点:

  • 安全性低,数据赤裸裸地暴露在地址栏中;

  • 如果数据量多,则整个 URL 变得臃肿不易维护。

多数据实例:

@RequestMapping("/response03")  
public String response03(ModelMap model) throws IOException {  
 // 发送给客户端的响应数据  
 String hello = "Hello";  
 model.addAttribute("data", hello);  
 model.addAttribute("id", 1);  
 return "redirect:/hello.jsp";  
}

3. 模板方式

Spring MVC 提供有一种所谓的模板方法,和前面的以查询字符串方法进行附加没有多大区别。如下面的代码,数据模型中的 data 对应数据会以 URL 变量方式传递。数据模型中其它数据则以查询字符串方式进行传递。

@RequestMapping("/response04")  
public String response04(ModelMap model) throws IOException {  
 // 发送给客户端的响应数据  
 String hello = "Hello";  
 model.addAttribute("data", hello);  
 model.addAttribute("id", 1);  
 return "redirect:/test/{data}";  
}@RequestMapping("/test/{data}")  
public String response05(@PathVariable("data") String data,@RequestParam("id") int id)  
 throws IOException {  
 System.out.println(data);  
 System.out.println(id);  
 return null;  
}

当在浏览器中请求 http://localhost:8888/sm-demo/response04 后,浏览器的地址栏中会变成 :http://localhost:8888/sm-demo/test/Hello?id=1

图片描述

模板方式其本质和查询字符串没有太多区别。

4. 使用 Flash 属性

Spring MVC 使用重定向时,内部会做些处理,把数据以查询字符串或变量参数方式进行传递。对于简单的数据传递已经足够了。如果需要传递一个对象,则需要把一个对象拆分后再传递,显然不是一种最佳方案。

Spring MVC 提供有 RedirectAttributes 组件,专用于重定向期间进行数据传递,其本质是把数据先保存在会话作用域中,但不会长时间占据会话存储空间,当整个重定向结束后数据会自动从会话作用域中删除。

所以,RedirectAttributes 组件中的属性也叫 Flash 属性。

如下面实例:用户对象以 Flash 属性的方式封装在模型对象中进行传递。

@RequestMapping("/response05")  
public String response06(RedirectAttributes model) throws IOException {  
 User user=new User("mk", "123");  
 model.addFlashAttribute("user", user);  
 return "redirect:/test01";  
}

Tips:重定向路径 test01 是控制器中的另一个方法,如下所示。

@RequestMapping("/test01")  
public String response07(ModelMap model)  
 throws IOException {  
 User user= (User) model.get("user");  
 System.out.println(user);  
 return "hello";  
}

自然,在 hello 视图中很便捷的就能得到数据。

<body>  
<div style="color:red"> ${user.userName} </div>   
<div style="color:red"> ${user.userPassword} </div>   
</body>

图片描述

4. 小结

本章节和大家一起讲解 Spring MVC 框架的重定向过程中是如何实现数据传递的,传递方式归纳起来就 2 种:

  • 通过 URL 附加数据的方式传递数据;
  • 使用 Spring MVC 提供的 RedirectAttributes 组件实现数据的传递。

两种方式各有属于自己的应用场景,数据量不多时可以使用第一种方案。数据以对象方式进行传递时可使用第二种方案。