View Resolution

Spring MVC 定义了 ViewResolver 和 View 接口,让你在浏览器中渲染模型,而不需要绑定到特定的视图技术。ViewResolver 提供了视图名称和实际视图之间的映射。视图解决了在移交给特定视图技术之前的数据准备。

下表提供了关于 ViewResolver 层次结构的更多细节:

ViewResolver Description
AbstractCachingViewResolver AbstractCachingViewResolver 的子类会缓存它们所解析的视图实例。缓存可以提高某些视图技术的性能。你可以通过将 cache 属性设置为 false 来关闭缓存。此外,如果你必须在运行时刷新某个视图(例如,当 FreeMarker 模板被修改时),你可以使用 removeFromCache(String viewName, Locale loc)方法。
UrlBasedViewResolver ViewResolver 接口的简单实现,无需明确的映射定义就能实现逻辑视图名称与 URL 的直接解析。如果你的逻辑名称与你的视图资源的名称直接匹配,而不需要任意的映射,这就很合适。
InternalResourceViewResolver UrlBasedViewResolver 的方便子类,支持 InternalResourceView(实际上是 Servlets 和 JSP)和子类,如 JstlView 和 TilesView。你可以通过使用 setViewClass(.) 为这个解析器生成的所有视图指定视图类。详情请参见 UrlBasedViewResolver javadoc
FreeMarkerViewResolver UrlBasedViewResolver 的方便子类,支持 FreeMarkerView 和它们的自定义子类。
ContentNegotiatingViewResolver ViewResolver 接口的实现,根据请求文件名或 Accept 头来解析视图。参见 内容协商
BeanNameViewResolver ViewResolver 接口的实现,它将视图名称解释为当前应用程序上下文中的 bean 名称。这是一个非常灵活的变体,可以根据不同的视图名称混合和匹配不同的视图类型。每个这样的视图都可以被定义为 Bean,例如在 XML 或配置类中。

Handling

你可以通过声明一个以上的解析器 Bean 来实现视图解析器的连锁,如果有必要,还可以通过设置 order 属性来指定排序。记住,顺序属性越高,视图解析器在链中的位置就越晚。

ViewResolver 的契约规定,它可以返回 null 以表示找不到视图。然而,在 JSP 和 InternalResourceViewResolver 的情况下,弄清 JSP 是否存在的唯一方法是通过 RequestDispatcher 进行调度。因此,你必须始终将 InternalResourceViewResolver 配置为在视图解析器的整体顺序中排在最后。

配置视图解析就像在 Spring 配置中添加 ViewResolver Bean 一样简单。MVC 配置为视图解析器和添加无逻辑的视图控制器提供了专门的配置 API,这对于没有控制器逻辑的 HTML 模板渲染很有用。

Redirecting / 重定向

Redirecting

视图名称中特殊的 redirect: 前缀可以让你执行重定向。UrlBasedViewResolver(和它的子类)将其识别为一个需要重定向的指令。视图名称的其余部分是重定向的 URL。

效果与控制器返回 RedirectView 的效果相同,但现在控制器本身可以在逻辑视图名称上操作。逻辑视图名称(如 redirect:/myapp/some/resource)是相对于当前 Servlet 上下文重定向的,而 redirect:[https://myhost.com/some/arbitrary/path](https://myhost.com/some/arbitrary/path)则是重定向到一个绝对 URL。

注意,如果一个控制器方法被 @ResponseStatus注解,该注解值优先于 RedirectView 设置的响应状态。

Forwarding / 转发

Forwarding

你也可以对最终由 UrlBasedViewResolver 和子类解析的视图名称使用一个特殊的 forward:前缀。这将创建一个 InternalResourceView,它做一个 RequestDispatcher.forward()。因此,这个前缀对 InternalResourceViewResolver 和 InternalResourceView(用于 JSP)没有用处,但如果你使用另一种视图技术,但仍想强制转发一个资源,由 Servlet/JSP 引擎处理,那么它就会有帮助。请注意,你也可以用链式的多个视图解析器来代替。

内容协商

Content Negotiation

ContentNegotiatingViewResolver 本身并不解析视图,而是委托给其他视图解析器,并选择与客户端请求的表示法相似的视图。表示法可以从接受头或查询参数(例如,"/path?format=pdf")中确定。

ContentNegotiatingViewResolver 通过比较请求的媒体类型和与其每个 ViewResolvers 相关的 View 所支持的媒体类型(也称为 Content-Type),选择一个适当的 View 来处理请求。列表中第一个具有兼容的内容类型的视图将表示返回给客户端。如果 ViewResolver 链不能提供兼容的视图,就会查询通过 DefaultViews 属性指定的视图列表。后面这个选项适合于单例视图,它可以渲染当前资源的适当表示,而不管逻辑视图名称如何。Accept 头可以包括通配符(例如 text/*),在这种情况下,内容类型为 text/xml的视图是一个兼容的匹配。

配置细节见 MVC 配置 下的 视图解析器