重定向时,会重新发起一个 URL 请求。之前请求过程中的数据就没有了,为此需要解决重定向时数据传输问题。
能够从发起重定向的方法传递数据给处理重定向方法中:
- 使用 URL 模板以路径变量和/或查询参数的形式传递数据;
- 通过 flash 属性发送数据。
1 通过 URL 模板进行重定向
除了连接 String 的方式来构建重定向 URL,Spring 还提供了使用模板的方式来定义重定向 URL。例如,在程序清单 5.19 中,processRegistration () 方法的最后一行可以改写为如下的形式:
@RequestMapping(value="/register", method=POST);
public String processRegistration(
Spitter spitter, Model model) {
spitterRepository.save(spitter);
model.addAttribute("spitterId", spitter.getId());
model.addAttribute("username", spitter.getUsername());
return "redirect:/spitter/{username}";
}除此之外,模型中所有其他的原始类型值都可以添加到 URL 中作为查询参数。作为样例,除了 username 以外,模型中还要包含新创建 Spitter 对象的 id 属性,那么结果得到的重定向 URL 路径将会是 /spitter/habuma?spitterId=42。
通过路径变量和查询参数的形式跨重定向传递数据是很简单直接的方式,但它也有一定的限制。它只能用来发送简单的值,如 String 和数字的值。在 URL 中,并没有办法发送更为复杂的值,但这正是 flash 属性能够提供帮助的领域。
2 使用 flash 属性
需要将 Spitter 对象放到一个位置,使其能够在重定向的过程中存活下来。
有个方案是将 Spitter 放到会话中。会话能够长期存在,并且能够跨多个请求。所以我们可以在重定向发生之前将 Spitter 放到会话中,并在重定向后,从会话中将其取出。当然,我们还要负责在重定向后在会话中将其清理掉。
实际上,Spring 也认为将跨重定向存活的数据放到会话中是一个很不错的方式。但是,Spring 认为我们并不需要管理这些数据,相反,Spring 提供了将数据发送为 flash 属性(flash attribute)的功能。按照定义,flash 属性会一直携带这些数据直到下一次请求,然后才会消失。
Spring 提供了通过 RedirectAttributes 设置 flash 属性的方法,这是 Spring 3.1 引入的 Model 的一个子接口。RedirectAttributes 提供了 Model 的所有功能,除此之外,还有几个方法是用来设置 flash 属性的。具体来讲,Redirect-Attributes 提供了一组 addFlashAttribute () 方法来添加 flash 属性。重新看一下 processRegistration () 方法,我们可以使用 addFlashAttribute () 将 Spitter 对象添加到模型中:
@RequestMapping(value="/register", method=POST)
public String processRegistration(
Spitter spitter, RedirectAttribute model) {
spitterRespository.save(spitter);
model.addAttribute("username", spitter.getUsername());
model.addFlashAttribute("spitter", spitter);
return "redirect:/spitter/{username}";
}在重定向执行之前,所有的 flash 属性都会复制到会话中。在重定向后,存在会话中的 flash 属性会被取出,并从会话转移到模型之中。
后续处理时,控制器先检查 model 中是否包含该对象。如果没有,再去存储中获取对应数据。