在程序开发中,重定向(redirect)是经常被用到的;当控制器Controller方法返回的String值以“redirect:”开头的话,那么这个String便不是来查找视图的,而是用来指导浏览器进行重定向的路径;
“redirect:”前缀能够让重定向功能变得非常简单,也许你觉得Spring这样处理重定向已经尽可能的简单了。但是:Spring还为重定向提供了一些其他的辅助功能。
具体来说,正在发起重定向功能的方法该如何发送数据给重定向的目标方法呢?一般来讲,当一个处理器方法完成之后,该方法所指定的模型数据将会复制到请求中,并作为请求中的属性,请求会转发(forward)到视图上进行渲染,因为控制器方法和视图所处理的是同一个请求,所以在转发的过程中请求属性能够得以保存。
但是当控制器的结果是重定向的话,原始的请求就结束了,并且会发起一个新的请求,原始请求中所带有的模型数据也随着请求一起消亡了。在新的请求属性中没有任何的模型数据,这个请求必须要自己计算数据。
显然对于重定向来说,模型并不能用来传递数据,但是我们也有一些其他的方案能够从发起重定向的方法传递数据给处理重定向方法中。
- 使用URL模板以路径变量、或查询参数的形式传递数据。
- 通过Flash属性发送数据。
通过URL模板进行重定向
如图:
使用flash属性
假设我们不想在重定向中发送username了,要发送实际的User对象。如果我们只发送对象ID的话,那么处理重定向的方法还需要从数据库中获取这个对象。但是在重定向之前我们已经获取到User对象了,应该直接发送User对象到处理重定向的方法;
但是,模型数据最终是以请求参数的形式复制到请求中的,当发生重定向的时候,这些数据就会丢失。因此我们需要将User对象放到一个位置,使其能够在重定向的过程中存活下来;也许有人会把对象放在会话中。会话能够长期存在,并且能跨域多个请求。所以在重定向发生之前,放入会话中即可;不过我们还要在重定向之后在会话中将其清理掉;
实际上,Spring也认为将跨重定向存活的数据放到会话中是一个很不错的方式,但是Spring认为我们并不需要管理这些数据,相反,Spring提供了将数据发送为flash属性(Flash attribute)的功能。按照定义,flash属性会一直携带这些数据,直到下一次请求,然后才会消失。
Spring提供了通过为ReditectAttributes设置flash属性的方法,但是Spring 3.1引入的model的一个子接口RedirectAttributes提供了Model的所有功能。除此之外,还有几个方法是用来设置flash属性的。具体代码如下
如图:
在这里,我们调用了addFlashAttribute()方法,将`User`作为key。User对象作为值。另外我们也可以不设置key参数,让Kay根据值的类型自定推断得出model.addFlushAttribute(user),因为我们传递了一个User对象给addFlushAttribute()方法,所以推断得到的key将会是User,在重定向执行之前,所有的Flash属性都会复制到会话中,在重定向之后存在会话中的flash属性会被取出,并会从会话转移到模型之中。处理定重定向的方法就能从模型中访问又在对象了,就像获取其他的模型对象一样。如下图
在从数据库查找之前,它会先从模型中检查User对象;
可以看到showUserObject方法所做的第一件事就是检查是否有Kay为User的model属性,如果模型中包含User属性,那就什么都不用做了,这里面包含的User对象将会传递到视图中进行渲染。但是如果模型中不包含User属性的话,那么收showUserObject将为从数据库中查找user并将其放到模型中。