视图重定向0 重定向视图 RedirectView1 向重定向目标传递数据2 重定向前缀——redirect:3 重定向前缀——forward:

控制器通常都会返回一个逻辑视图名,然后视图解析器会把它解析到一个具体的视图技术上去渲染。对于一些可以由Servlet或JSP引擎来处理的视图技术,比如JSP等,这个解析过程通常是由 InternalResourceViewResolver 和 InternalResourceView 协作来完成的,而这通常会调用ServletAPI RequestDispatcher.forward(..) 方法或 RequestDispatcher.include(..) 方法,并发生一次内部的转发(forward)或引用(include)。而对于其他的视图技术,比如Velocity、XSLT等,视图本身的内容是直接被写回响应流中的。 有时,我们想要在视图渲染之前,先把一个HTTP重定向请求发送回客户端。比如,当一个控 制器成功地接受到了 POST 过来的数据,而响应仅仅是委托另一个控制器来处理(比如一次成 功的表单提交)时,我们希望发生一次重定向。在这种场景下,如果只是简单地使用内部转 发,那么意味着下一个控制器也能看到这次 POST 请求携带的数据,这可能导致一些潜在的问 题,比如可能会与其他期望的数据混淆,等。此外,另一种在渲染视图前对请求进行重定向 的需求是,防止用户多次提交表单的数据。此时若使用重定向,则浏览器会先发送第一 个 POST 请求;请求被处理后浏览器会收到一个重定向响应,然后浏览器直接被重定向到一个 不同的URL,最后浏览器会使用重定向响应中携带的URL发起一次 GET 请求。因此,从浏览 器的角度看,当前所见的页面并不是 POST 请求的结果,而是一次 GET 请求的结果。这就防 止了用户因刷新等原因意外地提交了多次同样的数据。此时刷新会重新 GET 一次结果页,而 不是把同样的 POST 数据再发送一遍。

0 重定向视图 RedirectView

强制重定向的一种方法是,在控制器中创建并返回一个Spring重定向视图 RedirectView 的实例。它会使得 DispatcherServlet 放弃使用一般的视图解析机制,因为你已经返回一个(重定向)视图给 DispatcherServlet 了,所以它会构造一个视图来满足渲染的需求。紧接着 RedirectView 会调用 HttpServletResponse.sendRedirect() 方法,发送一个HTTP重定向响应给客户端浏览器。 如果你决定返回 RedirectView ,并且这个视图实例是由控制器内部创建出来的,那更推荐在外部配置重定向URL然后注入到控制器中来,而不是写在控制器里面。这样它就可以与视图名一起在配置文件中配置。关于如何实现这个解耦,参考 重定向前缀---redirect:

1 向重定向目标传递数据

模型中的所有属性默认都会考虑作为URI模板变量被添加到重定向URL中。剩下的其他属性,如果是基本类型或者基本类型的集合或数组,那它们将被自动添加到URL的查询参数中去。 如果model是专门为该重定向所准备的,那么把所有基本类型的属性添加到查询参数中可能是我们期望的那个结果。但是,在包含注解的控制器中,model可能包含了专门作为渲染用途的属性(比如一个下拉列表的字段值等)。为了避免把这样的属性也暴露在URL中, @RequestMapping 方法可以声明一个 RedirectAttributes 类型的方法参数,用它来指定专 门供重定向视图 RedirectView 取用的属性。如果重定向成功发生,那么 RedirectAttributes 对象中的内容就会被使用;否则使用模型model中的数据。 RequestMappingHandlerAdapter 提供了一个 "ignoreDefaultModelOnRedirect" 标志。它被用来标记默认 Model 中的属性永远不应该被用于控制器方法的重定向中。控制器方法应该声明一 个 RedirectAttributes 类的参数。如果不声明,那就没有参数被传递到重定向的视图 RedirectView 中。在MVC命名空间或MVC Java编程配置方式中,为了维持向后的兼容性,这个标志都仍被保持为 false 。但如果你的应用是一个新的项目,那么我们推荐把它的值设置成 true 。 请注意,当前请求URI中的模板变量会在填充重定向URL的时候自动对应用可见,而不需要显式地在 Model 或 RedirectAttributes 中再添加属性。请看下面的例子:

@RequestMapping(path = "/files/{path}", method = RequestMethod.POST)
public String upload(...) {
   // ...
   return "redirect:files/{path}";
}

另外一种向重定向目标传递数据的方法是通过 闪存属性(Flash Attributes)。与其他重定向属性不同,flash属性是存储在HTTP session中的(因此不会出现在URL中)。

2 重定向前缀——redirect:

尽管使用 RedirectView 来做重定向能工作得很好,但如果控制器自身还需要创建一个 RedirectView ,那无疑控制器还是了解重定向这么一件事情的发生。这还是有点不尽完美,不同范畴的耦合还是太强。控制器其实不应该去关心响应会如何被渲染。通常,它应该只关心被注入的视图的名字。 一个特别的视图名前缀能完成这个解耦: redirect: 。如果返回的视图名中含有 redirect: 前缀,那么 UrlBasedViewResolver (及它的所有子类)就会接受到这个信号,意识到这里需要发生重定向。然后视图名剩下的部分会被解析成重定向URL。 这种方式与通过控制器返回一个重定向视图 RedirectView 所达到的效果是一样的,不过这样一来控制器就可以只专注于处理并返回逻辑视图名了。如果逻辑视图名是这样的形 式: redirect:/myapp/some/resource ,他们重定向路径将以Servlet上下文作为相对路径进行查找,而逻辑视图名如果是这样的形式: redirect:http://myhost.com/some/arbitrary/path 那么重定向URL使用的就是绝对路径。 注意的是,如果控制器方法注解了 @ResponseStatus ,那么注解设置的状态码值会覆盖 RedirectView 设置的响应状态码值。

3 重定向前缀——forward:

对于最终会被 UrlBasedViewResolver 或其子类解析的视图名,你可以使用一个特殊的前缀: forward: 。这会导致一个 InternalResourceView 视图对象的创建(它最终会调用 RequestDispatcher.forward() 方法),后者会认为视图名剩下的部分是一个URL。因此,这个前缀在使用 InternalResourceViewResolver 和 InternalResourceView 时并没有特别的作用(比如对于JSP来说)。但当你主要使用的是其他的视图技术,而又想要强制把一个资源转发给Servlet/JSP引擎进行处理时,这个前缀可能就很有用(或者,你也可能同时串联多个视图解析器)。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏跟着阿笨一起玩NET

asp.net中使用swfupload上传大文件

转载:http://www.cnblogs.com/niunan/archive/2012/01/12/2320705.html

13540
来自专栏Albert陈凯

2018-11-19 Neo4j百万级数据导入只能用neo4j-import

业务需要使用Neo4j出数据关系展示图,数据库里有2张表通过一个字段进行关联,数据量是90万和500万,关系量是150w;

17020
来自专栏乐沙弥的世界

Percona XtraDB Cluster GCache和Record-Set缓存

在Percona XtraDB集群中,有一个GCache和Record-Set缓存(也可称为事务写集缓存)的概念。如果您正在运行长事务,那么使用这两个缓存通常会...

13800
来自专栏程序员互动联盟

【专业技术】8大你不得不知的Android调试工具

1. 查看当前堆栈 1) 功能:在程序中加入代码,使可以在logcat中看到打印出的当前函数调用关系 2) 方法: new Exception(“print ...

710130
来自专栏重庆的技术分享区

如何在Ubuntu 16.04上安装和配置Redis集群

Redis集群已经发展成为缓存,队列等的流行工具,因为它具有可扩展性和速度的潜力。本指南旨在使用三个Linode创建一个集群来演示分片。然后,如果发生故障,您将...

15060
来自专栏L宝宝聊IT

VBR的部署

23250
来自专栏前端杂货铺

服务端事件EventSource揭秘

服务端推 服务端推,指的是由服务器主动的向客户端发送消息(响应)。在应用层的HTTP协议实现中,“请求-响应”是一个round trip,它的起点来自客户端,因...

34350
来自专栏FreeBuf

手把手教你编写一个简单的PHP模块形态的后门

看到Freebuf 小编发表的用这个隐藏于PHP模块中的rootkit,就能持久接管服务器文章,很感兴趣,苦无作者没留下PoC,自己研究一番,有了此文 0x00...

51750
来自专栏Java帮帮-微信公众号-技术文章全总结

集群间如何实现session共享【面试+工作】

4.2K80
来自专栏容器云生态

企业网站架构之Nginx+tomcat+memcached集群

nginx+tomcat+memcached应用 系统环境:RHEL6.4  x64   iptables -F   and selinux is disab...

33080

扫码关注云+社区

领取腾讯云代金券