无论Controller是何种返回类型最终都会被封装成一个ModelAndView对象,然后交由ViewResolver解析成Vie对象。该接口定义非常简单,根据传入视图的逻辑名(var1)和相应的国际化信息返回View对象。
public interface ViewResolver { View resolveViewName(String var1, Locale var2) throws Exception; }
大部分接口的实现类是继承AbstractCachingViewResolver来简介实现该接口,AbstractCachingViewResolver提供了缓存视图对象的功能,也可以在配置视图解析器的时候禁用缓存来提高开发效率。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
<property name="cache" value="false"/>
</bean>
SpringMVC提供的ViewResolver可以分为两大类:面向单一视图和面向多视图类型。所谓面向单一视图指可通过视图模板的位置来定位视图,面向多视图需要额外的配置文件来确定视图。
面向单一视图
所有面向单一视图的视图解析器都直接或间接的继承自UrlBasedViewResolver,他们所具有的共同特点是只需要配置逻辑视图的位置,视图解析器就会利用视图模板和ModelAndView中的数据构建出View实例并返回。比如我们最常用的InternalResourceViewResolver,它负责从指定的位置找到JSP文件用于创建View模型。所以在配置这些视图的时候非常简单,只需要配上prefix和suffix即可。
面向多视图
国际化视图解析器是面向多视图的视图解析器中的代表,他需要额外配置国际化配置文件。
如果在SpringMVC容器中配置了多个视图解析器会怎么样呢?他会按照某种顺序遍历所有的ViewResolver知道有一个合适的视图解析器能够返回一个View对象,这种模型被称为ViewResolver查找序列。如果不指定的话该序列是配置顺序,作为Spring家族中的一员,SpringMVC中的ViewResolver同样实现了Order接口,允许我们指定ViewResolver在Chain上的顺序,如下所示。
但下面这种配置是有一定危险的,因为面向单一视图的视图解析器在解析失败的时候不会返回null然后用下一个视图解析器,返回null会造成404错误。所以在配置了多个视图解析器的情况下应该吧面向多视图的视图解析的order在前面。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
<property name="cache" value="false"/>
<property name="order" value="1"/>
</bean>