Spring-MVC跨重定向请求传递数据
处理完POST请求后, 通常来讲一个最佳实践就是执行一下重定向。 除了其他的一些因素外, 这样做能够防止用户点击
浏览器的刷新按钮或后退箭头时, 客户端重新执行危险的POST请求。
可以使用“redirect:”前缀的力量。 当控制器方法返回的String值以“redirect:”开头的话, 那么这个String不是用来查找视图的,而是用来指导浏览器进行重定向的路径 。
正在发起重定向功能的方法该如何发送数据给重定向的目标方法呢? 一般来讲, 当一个处理器方法完成之后, 该方法所指定的模型数据将会复制到请求中, 并作为请求中的属性, 请求会转发(forward) 到视图上进行渲染。 因为控制器方法和视图所处理的是同一个请求, 所以在转发的过程中, 请求属性能够得以保存。 当控制器的结果是重定向的话, 原始的请求就结束了, 并且会发起一个新的GET请求。 原始请求中所带有的模型数据也就随着请求一起消亡了。 在新的请求属性中, 没有任何的模型数据, 这个请求必须要自己计算数据 。
模型的属性是以请求属性的形式存放在请求中的, 在重定向后无法存活
显然, 对于重定向来说, 模型并不能用来传递数据 ,spring提供的以下解决方案:
- 使用URL模板以路径变量和/或查询参数的形式传递数据;
- 通过flash属性发送数据。
(1)通过URL模板进行重定向
第一种:
username作为占位符填充到了URL模板中, 而不是直接连接到重定向String中, 所以username中所有的不安全字符都会进行转义。 这样会更加安全, 这里允许用户输入任何想要的内容作为username, 并会将其附加到路径上。
第二种:
除此之外, 模型中所有其他的原始类型值都可以添加到URL中作为查询参数
模型中的phone属性没有匹配重定向URL中的任何占位符, 所以它会自动以查询参数的形式附加到重定向URL上。如果username属性的值是zhangsan并且phone属性的值是150xx,那么结果得到的重定向URL路径将会是“/index/zhangsan?phone=150xxx”。
(2)通过flash属性发送数据。
通过路径变量和查询参数的形式跨重定向传递数据是很简单直接的方式, 但它也有一定的限制。 它只能用来发送简单的值, 如String和数字的值。 在URL中, 并没有办法发送更为复杂的值,列如对象 但这正是flash属性能够提供帮助的领域。
假设我们不想在重定向中发送username或phone了, 而是要发送实际的User对象。 如果我们只发送phone的话, 那么处理重定向的方法会根据参数从数据库中查找才能得到User对象。 但是, 在重定向之前, 我们其实已经得到了User对象。 为什么不将其发送给处理重定向的方法, 并将其展现出来 .
正如我们前面所讨论的那样, 模型数据最终是以请求参数的形式复制到请求中的, 当重定向发生的时候, 这些数据就会丢失。 因此, 我们需要将User对象放到一个位置, 使其能够在重定向的过程中存活下来。有个方案是将User放到会话中。 会话能够长期存在, 并且能够跨多个请求。 所以我们可以在重定向发生之前将User放到会话中, 并在重定向后, 从会话中将其取出。 当然, 我们还要负责在重定向后在会话中将其清理掉。实际上, Spring也认为将跨重定向存活的数据放到会话中是一个很不错的方式。 但是, Spring认为我们并不需要管理这些数据, 相反, Spring提供了将数据发送为flash属性(flash attribute) 的功能。按照定义, flash属性会一直携带这些数据直到下一次请求, 然后才会消失.
Spring提供了通过RedirectAttributes设置flash属性的方法, 这是Spring 3.1引入的Model的一个子接口。 RedirectAttributes提供了Model的所有功能, 除此之外, 还有几个方法是用来设置flash属性的。