21.5.1 使用ViewResolver接口解析视图

正如在21.3 控制器的实现一节中所讨论的,Spring MVC中所有控制器的处理器方法都必须返回一个逻辑视图的名字,无论是显式返回(比如返回一个StringView或者ModelAndView)还是隐式返回(比如基于约定的返回)。Spring中的视图由一个视图名标识,并由视图解析器来渲染。Spring有非常多内置的视图解析器。下表列出了大部分,表后也给出了一些例子。

表21.3 视图解析器

视图解析器 描述
AbstractCachingViewResolver 一个抽象的视图解析器类,提供了缓存视图的功能。通常视图在能够被使用之前需要经过准备。继承这个基类的视图解析器即可以获得缓存视图的能力。
XmlViewResolver 视图解析器接口ViewResolver的一个实现,该类接受一个XML格式的配置文件。该XML文件必须与Spring XML的bean工厂有相同的DTD。默认的配置文件名是/WEB-INF/views.xml
ResourceBundleViewResolver 视图解析器接口ViewResolver的一个实现,采用bundle根路径所指定的ResourceBundle中的bean定义作为配置。一般bundle都定义在classpath路径下的一个配置文件中。默认的配置文件名为views.properties
UrlBasedViewResolver ViewResolver接口的一个简单实现。它直接使用URL来解析到逻辑视图名,除此之外不需要其他任何显式的映射声明。如果你的逻辑视图名与你真正的视图资源名是直接对应的,那么这种直接解析的方式就很方便,不需要你再指定额外的映射。
InternalResourceViewResolver UrlBasedViewResolver的一个好用的子类。它支持内部资源视图(具体来说,Servlet和JSP)、以及诸如JstlViewTilesView等类的子类。You can specify the view class for all views generated by this resolver by using setViewClass(..)。更多的细节,请见UrlBasedViewResolver类的java文档。
VelocityViewResolver / FreeMarkerViewResolver UrlBasedViewResolver下的实用子类,支持Velocity视图VelocityView(Velocity模板)和FreeMarker视图FreeMarkerView以及它们对应子类。
ContentNegotiatingViewResolver 视图解析器接口ViewResolver的一个实现,它会根据所请求的文件名或请求的Accept头来解析一个视图。更多细节请见21.5.4 内容协商视图解析器"ContentNegotiatingViewResolver"一小节。

我们可以举个例子,假设这里使用的是JSP视图技术,那么我们可以使用一个基于URL的视图解析器UrlBasedViewResolver。这个视图解析器会将URL解析成一个视图名,并将请求转交给请求分发器来进行视图渲染。

<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

若返回一个test逻辑视图名,那么该视图解析器会将请求转发到RequestDispatcher,后者会将请求交给/WEB-INF/jsp/test.jsp视图去渲染。

如果需要在应用中使用多种不同的视图技术,你可以使用ResourceBundleViewResolver

<bean id="viewResolver"
        class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    <property name="basename" value="views"/>
    <property name="defaultParentView" value="parentView"/>
</bean>

ResourceBundleViewResolver会检索由bundle根路径下所配置的ResourceBundle,对于每个视图而言,其视图类由[viewname].(class)属性的值指定,其视图url由[viewname].url属性的值指定。下一节将详细讲解视图技术,你可以在那里找到更多例子。你还可以看到,视图还允许有基视图,即properties文件中所有视图都“继承”的一个文件。通过继承技术,你可以为众多视图指定一个默认的视图基类。

AbstractCachingViewResolver的子类能够缓存已经解析过的视图实例。关闭缓存特性也是可以的,只需要将cache属性设置为false即可。另外,如果实在需要在运行时刷新某个视图(比如修改了Velocity模板时),你可以使用removeFromCache(String viewName, Locale loc)方法。`