# 使用ViewResolver接口解析视图

正如在[21.3 控制器的实现](http://docs.spring.io/spring-framework/docs/4.2.4.RELEASE/spring-framework-reference/html/mvc.html#mvc-controller)一节中所讨论的，Spring MVC中所有控制器的处理器方法都必须返回一个逻辑视图的名字，无论是显式返回（比如返回一个`String`、`View`或者`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）、以及诸如`JstlView`和`TilesView`等类的子类。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"](http://docs.spring.io/spring-framework/docs/4.2.4.RELEASE/spring-framework-reference/html/mvc.html#mvc-multiple-representations)一小节。 |

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

```markup
<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`：

```markup
<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)`方法。\`
