Spring MVC设置多个ViewResolver视图解析器

Spring MVC常用的ViewResolver

1. InternalResourceViewResolver

InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。比如在InternalResourceViewResolver中定义了prefix=/WEB-INF/,suffix=.jsp,然后请求的Controller处理器方法返回的视图名称为test,那么这个时候InternalResourceViewResolver就会把test解析为一个InternalResourceView对象,先把返回的模型属性都存放到对应的HttpServletRequest属性中,然后利用RequestDispatcher在服务器端把请求forword到/WEB-INF/test.jsp。

2. BeanNameViewResolver

这个视图解析器跟XmlViewResolver有点类似,也是通过把返回的逻辑视图名称去匹配定义好的视图bean对象。不同点有二,一是BeanNameViewResolver要求视图bean对象都定义在Spring的application context中,而XmlViewResolver是在指定的配置文件中寻找视图bean对象,二是BeanNameViewResolver不会进行视图缓存。

3. ResourceBundleViewResolver

它和XmlViewResolver一样,也是继承自AbstractCachingViewResolver,但是它缓存的不是视图,这个会在后面有说到。和XmlViewResolver一样它也需要有一个配置文件来定义逻辑视图名称和真正的View对象的对应关系,不同的是ResourceBundleViewResolver的配置文件是一个属性文件,而且必须是放在classpath路径下面的,默认情况下这个配置文件是在classpath根目录下的views.properties文件,如果不使用默认值的话,则可以通过属性baseName或baseNames来指定。baseName只是指定一个基名称,Spring会在指定的classpath根目录下寻找以指定的baseName开始的属性文件进行View解析,如指定的baseName是base,那么base.properties、baseabc.properties等等以base开始的属性文件都会被Spring当做ResourceBundleViewResolver解析视图的资源文件。

4. XmlViewResolver

XmlViewResolver需要给定一个xml配置文件,该文件将使用和Spring的bean工厂配置文件一样的DTD定义,所以其实该文件就是用来定义视图的bean对象的。在该文件中定义的每一个视图的bean对象都给定一个名字,然后XmlViewResolver将根据Controller处理器方法返回的逻辑视图名称到XmlViewResolver指定的配置文件中寻找对应名称的视图bean用于处理视图。该配置文件默认是/WEB-INF/views.xml文件,如果不使用默认值的时候可以在XmlViewResolver的location属性中指定它的位置。XmlViewResolver还实现了Ordered接口,因此我们可以通过其order属性来指定在ViewResolver链中它所处的位置,order的值越小优先级越高。

Spring MVC设置多个ViewResolver视图解析器

当我们需要多个viewResolver的时候,spring 框架为我们提供了很好的支持,我们只要在[spring-dispatcher-name]-servlet.xml中定义多个ViewResolver就可以了。

<!-- 定义JSP视图解析器-->  
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/"></property>
    <property name="suffix" value=".jsp"></property>
    <property name="order" value="1" />
</bean>

<bean id="freemarkerViewResolver" class="com.founder.web.commom.springmvc.view.ExtFreeMarkerViewResolver">
    <property name="contentType" value="text/html; charset=UTF-8"/>
    <property name="exposeRequestAttributes" value="false"/>
    <property name="exposeSessionAttributes" value="false"/>
    <property name="exposeSpringMacroHelpers" value="true"/>
    <property name="cacheUnresolved" value="false"/>
    <property name="order" value="0" />
</bean>

实例

1. 新建一个html的解析器并继承 InternalResourceView 后重写 checkResource

package com.izhbg.typz.common.springmvc.view;  
import java.io.File;  
import java.util.Locale;  
  
import org.springframework.web.servlet.view.InternalResourceView;  
public class HtmlResourceView extends InternalResourceView {  
     @Override  
     public boolean checkResource(Locale locale) {  
      File file = new File(this.getServletContext().getRealPath("/") + getUrl());  
      return file.exists();// 判断该页面是否存在  
     }  
} 

2. 在xml配置文件中 指定解析器的 viewClass为该解析类

<bean id="htmlviewResolver"      class="org.springframework.web.servlet.view.InternalResourceViewResolver">     <property name="viewClass" value="com.izhbg.typz.common.springmvc.view.HtmlResourceView"/>    <property name="order" value="0" />    <property name="prefix" value="/cms/"/>    <property name="suffix" value=".html" />      <property name="contentType" value="text/html;charset=UTF-8"></property>    
</bean>  
<!-- 定义JSP文件的位置 -->  
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">    <property name="order" value="1" />    <property name="prefix" value="/views/"/>    <property name="suffix" value=".jsp"/>  
</bean>  

总结

1. 如果某个解析器没有找到合适的视图,Spring会在上下文中寻找是否配置了其它的解析器。 如果有,它会继续进行解析,否则,Srping会抛出一个Exception。

2. 当一个视图解析器找不到合适的视图时,它可能返回null值。 但是不是每个解析器都这么做。这是因为,在某些情况下,解析器可能无法侦测出符合要求的视图是否存在。 比如,InternalResourceViewResolver在内部调用了RequestDispatcher。 请求分发是检查一个JSP文件是否存在的唯一方法,不幸的是,这个方法只能用一次。 同样的问题在VelocityViewResolver和其它解析器中也有。 当使用这些解析器时,最好仔细阅读它们的Javadoc,看看需要的解析器是否无法发现不存在的视图。 这个问题产生的副作用是,如果InternalResourceViewResolver解析器没有放在链的末端, InternalResourceViewResolver后面的那些解析器根本得不到使用, 因为InternalResourceViewResolver总是返回一个视图!

版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。