Spring MVC-從零開始-view-ViewResolver

主要ViewResolver簡介html

InternalResourceViewResolver 將邏輯視圖名解析爲一個路徑
BeanNameViewResolver 將邏輯視圖名解析爲bean的name屬性,從而根據name屬性去找對應的bean
ResourceBundleResolver 和BeanNameViewResolver同樣,只不過定義的view-bean都在一個properties文件中,用這個類進行加載這個properties文件
XmlViewResolver 和ResourceBundleResolver同樣,只不過定義的view-bean在一個xml文件中,用這個類來加載xml文件
UrlBasedViewResolver 它簡單實現了ViewResolver接口, 不用任何映射就能經過邏輯視圖名稱訪問資源
VelocityViewResolver 對Velocity模版引擎的支持
FreeMarkerViewResolver 對FreeMarker模版引擎的支持

 

 

 

 

 

 

 

轉載(SpringMVC介紹之視圖解析器ViewResolverjava

 

SpringMVC視圖解析器web

前言

   在前一篇博客中講了SpringMVC的Controller控制器,在這篇博客中將接着介紹一下SpringMVC視圖解析器。當咱們對SpringMVC控制的資源發起請求時,這些請求都會被SpringMVC的DispatcherServlet處理,接着Spring會分析看哪個HandlerMapping定義的全部請求映射中存在對該請求的最合理的映射。而後經過該HandlerMapping取得其對應的Handler,接着再經過相應的HandlerAdapter處理該Handler。HandlerAdapter在對Handler進行處理以後會返回一個ModelAndView對象。在得到了ModelAndView對象以後,Spring就須要把該View渲染給用戶,即返回給瀏覽器。在這個渲染的過程當中,發揮做用的就是ViewResolver和View。當Handler返回的ModelAndView中不包含真正的視圖,只返回一個邏輯視圖名稱的時候,ViewResolver就會把該邏輯視圖名稱解析爲真正的視圖View對象。View是真正進行視圖渲染,把結果返回給瀏覽器的。spring

ViewResolver和View介紹

SpringMVC用於處理視圖最重要的兩個接口是ViewResolver和View。ViewResolver的主要做用是把一個邏輯上的視圖名稱解析爲一個真正的視圖,SpringMVC中用於把View對象呈現給客戶端的是View對象自己,而ViewResolver只是把邏輯視圖名稱解析爲對象的View對象。View接口的主要做用是用於處理視圖,而後返回給客戶端。瀏覽器

Spring爲咱們提供了很是多的視圖解析器,下面將列舉一些視圖解析器。緩存

AbstractCachingViewResolver:這是一個抽象類,這種視圖解析器會把它曾經解析過的視圖保存起來,而後每次要解析視圖的時候先從緩存裏面找,若是找到了對應的視圖就直接返回,若是沒有就建立一個新的視圖對象,而後把它放到一個用於緩存的map中,接着再把新建的視圖返回。使用這種視圖緩存的方式能夠把解析視圖的性能問題降到最低。安全

UrlBasedViewResolver:它是對ViewResolver的一種簡單實現,並且繼承了AbstractCachingViewResolver,主要就是提供的一種拼接URL的方式來解析視圖,它可讓咱們經過prefix屬性指定一個指定的前綴,經過suffix屬性指定一個指定的後綴,而後把返回的邏輯視圖名稱加上指定的前綴和後綴就是指定的視圖URL了。如prefix=/WEB-INF/jsps/,suffix=.jsp,返回的視圖名稱viewName=test/indx,則UrlBasedViewResolver解析出來的視圖URL就是/WEB-INF/jsps/test/index.jsp。默認的prefix和suffix都是空串。URLBasedViewResolver支持返回的視圖名稱中包含redirect:前綴,這樣就能夠支持URL在客戶端的跳轉,如當返回的視圖名稱是」redirect:test.do」的時候,URLBasedViewResolver發現返回的視圖名稱包含」redirect:」前綴,因而把返回的視圖名稱前綴」redirect:」去掉,取後面的test.do組成一個RedirectView,RedirectView中將把請求返回的模型屬性組合成查詢參數的形式組合到redirect的URL後面,而後調用HttpServletResponse對象的sendRedirect方法進行重定向。一樣URLBasedViewResolver還支持forword:前綴,對於視圖名稱中包含forword:前綴的視圖名稱將會被封裝成一個InternalResourceView對象,而後在服務器端利用RequestDispatcher的forword方式跳轉到指定的地址。使用UrlBasedViewResolver的時候必須指定屬性viewClass,表示解析成哪一種視圖,通常使用較多的就是InternalResourceView,利用它來展示jsp,可是當咱們使用JSTL的時候咱們必須使用JstlView。下面是一段UrlBasedViewResolver的定義,根據該定義,當返回的邏輯視圖名稱是test的時候,UrlBasedViewResolver將把邏輯視圖名稱加上定義好的前綴和後綴,即「/WEB-INF/test.jsp」,而後新建一個viewClass屬性指定的視圖類型予以返回,即返回一個url爲「/WEB-INF/test.jsp」的InternalResourceView對象。服務器

Xml代碼  
  1. <bean  
  2.    class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
  3.    <property name="prefix" value="/WEB-INF/" />  
  4.    <property name="suffix" value=".jsp" />  
  5.    <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>  
  6. </bean>  
    <bean
       class="org.springframework.web.servlet.view.UrlBasedViewResolver">
       <property name="prefix" value="/WEB-INF/" />
       <property name="suffix" value=".jsp" />
       <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
    </bean>

 

InternalResourceViewResolver:它是URLBasedViewResolver的子類,因此URLBasedViewResolver支持的特性它都支持。在實際應用中InternalResourceViewResolver也是使用的最普遍的一個視圖解析器。那麼InternalResourceViewResolver有什麼本身獨有的特性呢?單從字面意思來看,咱們能夠把InternalResourceViewResolver解釋爲內部資源視圖解析器,這就是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。這就是InternalResourceViewResolver一個很是重要的特性,咱們都知道存放在/WEB-INF/下面的內容是不能直接經過request請求的方式請求到的,爲了安全性考慮,咱們一般會把jsp文件放在WEB-INF目錄下,而InternalResourceView在服務器端跳轉的方式能夠很好的解決這個問題。下面是一個InternalResourceViewResolver的定義,根據該定義當返回的邏輯視圖名稱是test的時候,InternalResourceViewResolver會給它加上定義好的前綴和後綴,組成「/WEB-INF/test.jsp」的形式,而後把它當作一個InternalResourceView的url新建一個InternalResourceView對象返回。app

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
  2.    <property name="prefix" value="/WEB-INF/"/>  
  3.    <property name="suffix" value=".jsp"></property>  
  4. </bean>  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/WEB-INF/"/>
       <property name="suffix" value=".jsp"></property>
    </bean>

 

XmlViewResolver:它繼承自AbstractCachingViewResolver抽象類,因此它也是支持視圖緩存的。XmlViewResolver須要給定一個xml配置文件,該文件將使用和Spring的bean工廠配置文件同樣的DTD定義,因此其實該文件就是用來定義視圖的bean對象的。在該文件中定義的每個視圖的bean對象都給定一個名字,而後XmlViewResolver將根據Controller處理器方法返回的邏輯視圖名稱到XmlViewResolver指定的配置文件中尋找對應名稱的視圖bean用於處理視圖。該配置文件默認是/WEB-INF/views.xml文件,若是不使用默認值的時候能夠在XmlViewResolver的location屬性中指定它的位置。XmlViewResolver還實現了Ordered接口,所以咱們能夠經過其order屬性來指定在ViewResolver鏈中它所處的位置,order的值越小優先級越高。如下是使用XmlViewResolver的一個示例:jsp

(1)在SpringMVC的配置文件中加入XmlViewResolver的bean定義。使用location屬性指定其配置文件所在的位置,order屬性指定當有多個ViewResolver的時候其處理視圖的優先級。關於ViewResolver鏈的問題將在後續內容中講到。

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.XmlViewResolver">  
  2.    <property name="location" value="/WEB-INF/views.xml"/>  
  3.    <property name="order" value="1"/>  
  4. </bean>  
    <bean class="org.springframework.web.servlet.view.XmlViewResolver">
       <property name="location" value="/WEB-INF/views.xml"/>
       <property name="order" value="1"/>
    </bean>

 

(2)在XmlViewResolver對應的配置文件中配置好所須要的視圖定義。在下面的代碼中咱們就配置了一個名爲internalResource的InternalResourceView,其url屬性爲「/index.jsp」。

Xml代碼  
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  
  6.     <bean id="internalResource" class="org.springframework.web.servlet.view.InternalResourceView">  
  7.        <property name="url" value="/index.jsp"/>  
  8.     </bean>  
  9. </beans>  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="internalResource" class="org.springframework.web.servlet.view.InternalResourceView">
       <property name="url" value="/index.jsp"/>
    </bean>
</beans>

 

(3)定義一個返回的邏輯視圖名稱爲在XmlViewResolver配置文件中定義的視圖名稱——internalResource。

Java代碼  
  1. @RequestMapping("/xmlViewResolver")  
  2. public String testXmlViewResolver() {  
  3.    return "internalResource";  
  4. }  
    @RequestMapping("/xmlViewResolver")
    public String testXmlViewResolver() {
       return "internalResource";
    }

 

(4)這樣當咱們訪問到上面定義好的testXmlViewResolver處理器方法的時候返回的邏輯視圖名稱爲「internalResource」,這時候Spring就會到定義好的views.xml中尋找id或name爲「internalResource」的bean對象予以返回,這裏Spring找到的是一個url爲「/index.jsp」的InternalResourceView對象。

BeanNameViewResolver:這個視圖解析器跟XmlViewResolver有點相似,也是經過把返回的邏輯視圖名稱去匹配定義好的視圖bean對象。不一樣點有二,一是BeanNameViewResolver要求視圖bean對象都定義在Spring的application context中,而XmlViewResolver是在指定的配置文件中尋找視圖bean對象,二是BeanNameViewResolver不會進行視圖緩存。看一個例子,在SpringMVC的配置文件中定義了一個BeanNameViewResolver視圖解析器和一個id爲test的InternalResourceview bean對象。

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">  
  2.    <property name="order" value="1"/>  
  3. </bean>  
  4.   
  5. <bean id="test" class="org.springframework.web.servlet.view.InternalResourceView">  
  6.    <property name="url" value="/index.jsp"/>  
  7. </bean>  
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
       <property name="order" value="1"/>
    </bean>

    <bean id="test" class="org.springframework.web.servlet.view.InternalResourceView">
       <property name="url" value="/index.jsp"/>
    </bean>

 

這樣當返回的邏輯視圖名稱是 test的時候,就會解析爲上面定義好id爲test的InternalResourceView。

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解析視圖的資源文件。ResourceBundleViewResolver使用的屬性配置文件的內容相似於這樣:

Properties代碼  
  1. resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView  
  2. resourceBundle.url=/index.jsp  
  3. test.(class)=org.springframework.web.servlet.view.InternalResourceView  
  4. test.url=/test.jsp  
resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView
resourceBundle.url=/index.jsp
test.(class)=org.springframework.web.servlet.view.InternalResourceView
test.url=/test.jsp

 

在這個配置文件中咱們定義了兩個InternalResourceView對象,一個的名稱是resourceBundle,對應URL是/index.jsp,另外一個名稱是test,對應的URL是/test.jsp。從這個定義來看咱們能夠知道resourceBundle是對應的視圖名稱,使用resourceBundle.(class)來指定它對應的視圖類型,resourceBundle.url指定這個視圖的url屬性。會思考的讀者看到這裏可能會有這樣一個問題:爲何resourceBundle的class屬性要用小括號包起來,而它的url屬性就不須要呢?這就須要從ResourceBundleViewResolver進行視圖解析的方法來講了。ResourceBundleViewResolver仍是經過bean工廠來得到對應視圖名稱的視圖bean對象來解析視圖的。那麼這些bean從哪裏來呢?就是從咱們定義的properties屬性文件中來。在ResourceBundleViewResolver第一次進行視圖解析的時候會先new一個BeanFactory對象,而後把properties文件中定義好的屬性按照它自身的規則生成一個個的bean對象註冊到該BeanFactory中,以後會把該BeanFactory對象保存起來,因此ResourceBundleViewResolver緩存的是BeanFactory,而不是直接的緩存從BeanFactory中取出的視圖bean。而後會從bean工廠中取出名稱爲邏輯視圖名稱的視圖bean進行返回。接下來就講講Spring經過properties文件生成bean的規則。它會把properties文件中定義的屬性名稱按最後一個點「.」進行分割,把點前面的內容當作是bean名稱,點後面的內容當作是bean的屬性。這其中有幾個特別的屬性,Spring把它們用小括號包起來了,這些特殊的屬性通常是對應的attribute,但不是bean對象全部的attribute均可以這樣用。其中(class)是一個,除了(class)以外,還有(scope)、(parent)、(abstract)、(lazy-init)。而除了這些特殊的屬性以外的其餘屬性,Spring會把它們當作bean對象的通常屬性進行處理,就是bean對象對應的property。因此根據上面的屬性配置文件將生成以下兩個bean對象:

Xml代碼  
  1. <bean id="resourceBundle" class="org.springframework.web.servlet.view.InternalResourceView">  
  2.    <property name="url" value="/index.jsp"/>  
  3. </bean>  
  4.   
  5. <bean id="test" class="org.springframework.web.servlet.view.InternalResourceView">  
  6.    <property name="url" value="/test.jsp"/>  
  7. </bean>  
    <bean id="resourceBundle" class="org.springframework.web.servlet.view.InternalResourceView">
       <property name="url" value="/index.jsp"/>
    </bean>

    <bean id="test" class="org.springframework.web.servlet.view.InternalResourceView">
       <property name="url" value="/test.jsp"/>
    </bean>

 

從ResourceBundleViewResolver使用的配置文件咱們能夠看出,它和XmlViewResolver同樣能夠解析多種不一樣類型的View,由於它們的View是經過配置的方式指定的,這也就意味着咱們能夠指定A視圖是InternalResourceView,B視圖是JstlView。

來看下面這個一個例子,我在SpringMVC的配置文件中定義了一個ResourceBundleViewResolver對象,指定其baseName爲views,而後order爲1。

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">  
  2.    <property name="basename" value="views"/>  
  3.    <property name="order" value="1"/>  
  4. </bean>  
    <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
       <property name="basename" value="views"/>
       <property name="order" value="1"/>
    </bean>

 

我在classpath的根目錄下有兩個屬性文件,一個是views.properties,一個是views_abc.properties,它們的內容分別以下:

views.properties:

Properties代碼  
  1. resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView  
  2. resourceBundle.url=/index.jsp  
  3. test.(class)=org.springframework.web.servlet.view.InternalResourceView  
  4. test.url=/test.jsp  
resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView
resourceBundle.url=/index.jsp
test.(class)=org.springframework.web.servlet.view.InternalResourceView
test.url=/test.jsp

 

views_abc.properties:

Properties代碼  
  1. abc.(class)=org.springframework.web.servlet.view.InternalResourceView  
  2. abc.url=/abc.jsp  
abc.(class)=org.springframework.web.servlet.view.InternalResourceView
abc.url=/abc.jsp

 

定義了以下這樣一個Controller,它有三個處理器方法。

Java代碼  
  1. @Controller  
  2. @RequestMapping("/mytest")  
  3. public class MyController {  
  4.     @RequestMapping("resourceBundle")  
  5.     public String resourceBundle() {  
  6.        return "resourceBundle";  
  7.     }  
  8.   
  9.     @RequestMapping("testResourceBundle")  
  10.     public String testResourceBundle() {  
  11.        return "test";  
  12.     }  
  13.   
  14.     @RequestMapping("abc")  
  15.     public String abc() {  
  16.        return "abc";  
  17.     }  
  18.   
  19. }  
@Controller
@RequestMapping("/mytest")
public class MyController {
    @RequestMapping("resourceBundle")
    public String resourceBundle() {
       return "resourceBundle";
    }

    @RequestMapping("testResourceBundle")
    public String testResourceBundle() {
       return "test";
    }

    @RequestMapping("abc")
    public String abc() {
       return "abc";
    }

}

 

那麼當咱們請求/mytest/resourceBundle.do的時候,ResourceBundleViewResolver會首先嚐試着來解析該視圖,這裏Controller處理器方法返回的邏輯視圖名稱是resourceBundle,ResourceBundleViewResolver按照上面提到的解析方法進行解析,這個時候它發現它是能夠解析的,而後就返回了一個url爲/index.jsp的InternalResourceView對象。一樣,請求/mytest/testResourceBundle.do返回的邏輯視圖test和/mytest/abc.do返回的邏輯視圖abc它均可以解析。當咱們把basename指定爲包的形式,如「com.tiantian.views」,的時候Spring會按照點「.」劃分爲目錄的形式,到classpath相應目錄下去尋找basename開始的配置文件,如上面咱們指定basename爲「com.tiantian.views」,那麼spring就會到classpath下的com/tiantian目錄下尋找文件名以views開始的properties文件做爲解析視圖的配置文件。

FreeMarkerViewResolverVolocityViewResolver:這兩個視圖解析器都是UrlBasedViewResolver的子類。FreeMarkerViewResolver會把Controller處理方法返回的邏輯視圖解析爲FreeMarkerView,而VolocityViewResolver會把返回的邏輯視圖解析爲VolocityView。由於這兩個視圖解析器相似,因此這裏我就只挑FreeMarkerViewResolver來作一個簡單的講解。FreeMarkerViewResolver和VilocityViewResolver都繼承了UrlBasedViewResolver。

對於FreeMarkerViewResolver而言,它會按照UrlBasedViewResolver拼接URL的方式進行視圖路徑的解析。可是使用FreeMarkerViewResolver的時候不須要咱們指定其viewClass,由於FreeMarkerViewResolver中已經把viewClass定死爲FreeMarkerView了。

咱們先在SpringMVC的配置文件裏面定義一個FreeMarkerViewResolver視圖解析器,並定義其解析視圖的order順序爲1。

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
  2.    <property name="prefix" value="fm_"/>  
  3.    <property name="suffix" value=".ftl"/>  
  4.    <property name="order" value="1"/>  
  5. </bean>  
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
       <property name="prefix" value="fm_"/>
       <property name="suffix" value=".ftl"/>
       <property name="order" value="1"/>
    </bean>

 

那麼當咱們請求的處理器方法返回一個邏輯視圖名稱viewName的時候,就會被該視圖處理器加上先後綴解析爲一個url爲「fm_viewName.ftl」的FreeMarkerView對象。對於FreeMarkerView咱們須要給定一個FreeMarkerConfig的bean對象來定義FreeMarker的配置信息。FreeMarkerConfig是一個接口,Spring已經爲咱們提供了一個實現,它就是FreeMarkerConfigurer。咱們能夠經過在SpringMVC的配置文件裏面定義該bean對象來定義FreeMarker的配置信息,該配置信息將會在FreeMarkerView進行渲染的時候使用到。對於FreeMarkerConfigurer而言,咱們最簡單的配置就是配置一個templateLoaderPath,告訴Spring應該到哪裏尋找FreeMarker的模板文件。這個templateLoaderPath也支持使用「classpath:」和「file:」前綴。當FreeMarker的模板文件放在多個不一樣的路徑下面的時候,咱們可使用templateLoaderPaths屬性來指定多個路徑。在這裏咱們指定模板文件是放在「/WEB-INF/freemarker/template」下面的。

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
  2.    <property name="templateLoaderPath" value="/WEB-INF/freemarker/template"/>  
  3. </bean>  
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
       <property name="templateLoaderPath" value="/WEB-INF/freemarker/template"/>
    </bean>

 

接下來咱們定義以下一個Controller:

Java代碼  
  1. @Controller  
  2. @RequestMapping("/mytest")  
  3. public class MyController {  
  4.   
  5.     @RequestMapping("freemarker")  
  6.     public ModelAndView freemarker() {  
  7.        ModelAndView mav = new ModelAndView();  
  8.        mav.addObject("hello", "andy");  
  9.        mav.setViewName("freemarker");  
  10.        return mav;  
  11.     }  
  12.   
  13. }  
@Controller
@RequestMapping("/mytest")
public class MyController {

    @RequestMapping("freemarker")
    public ModelAndView freemarker() {
       ModelAndView mav = new ModelAndView();
       mav.addObject("hello", "andy");
       mav.setViewName("freemarker");
       return mav;
    }

}

 

由上面的定義咱們能夠看到這個Controller的處理器方法freemarker返回的邏輯視圖名稱是「freemarker」。那麼若是咱們須要把該freemarker視圖交給FreeMarkerViewResolver來解析的話,咱們就須要根據上面的定義,在模板路徑下定義視圖對應的模板,即在「/WEB-INF/freemarker/template」目錄下創建fm_freemarker.ftl模板文件。這裏咱們定義其內容以下:

Ftl代碼  
  1. <html>  
  2.     <head>  
  3.        <title>FreeMarker</title>  
  4.     </head>  
  5.     <body>  
  6.        <b>Hello World</b>  
  7.        <font color="red">Hello World!</font>  
  8.        ${hello}  
  9.     </body>  
  10. </html>  
<html>
    <head>
       <title>FreeMarker</title>
    </head>
    <body>
       <b>Hello World</b>
       <font color="red">Hello World!</font>
       ${hello}
    </body>
</html>

 

通過上面的定義當咱們訪問/mytest/freemarker.do的時候就會返回一個邏輯視圖名稱爲「freemarker」的ModelAndView對象,根據定義好的視圖解析的順序,首先進行視圖解析的是FreeMarkerViewResolver,這個時候FreeMarkerViewResolver會試着解析該視圖,根據它自身的定義,它會先解析到該視圖的URL爲fm_freemarker.ftl,而後它會看是否可以實例化該視圖對象,即在定義好的模板路徑下是否有該模板存在,若是有則返回該模板對應的FreeMarkerView。在這裏的話/WEB-INF/freemarker/template目錄下是存在模板文件fm_freemarker.ftl的,因此會返回一個url爲fm_freemarker.ftl的FreeMarkerView對象。接着FreeMarkerView就能夠利用該模板文件進行視圖的渲染了。因此訪問結果應該以下所示:  

 

視圖解析器鏈

       在SpringMVC中能夠同時定義多個ViewResolver視圖解析器,而後它們會組成一個ViewResolver鏈。當Controller處理器方法返回一個邏輯視圖名稱後,ViewResolver鏈將根據其中ViewResolver的優先級來進行處理。全部的ViewResolver都實現了Ordered接口,在Spring中實現了這個接口的類都是能夠排序的。在ViewResolver中是經過order屬性來指定順序的,默認都是最大值。因此咱們能夠經過指定ViewResolver的order屬性來實現ViewResolver的優先級,order屬性是Integer類型,order越小,對應的ViewResolver將有越高的解析視圖的權利,因此第一個進行解析的將是ViewResolver鏈中order值最小的那個。當一個ViewResolver在進行視圖解析後返回的View對象是null的話就表示該ViewResolver不能解析該視圖,這個時候若是還存在其餘order值比它大的ViewResolver就會調用剩餘的ViewResolver中的order值最小的那個來解析該視圖,依此類推。當ViewResolver在進行視圖解析後返回的是一個非空的View對象的時候,就表示該ViewResolver可以解析該視圖,那麼視圖解析這一步就完成了,後續的ViewResolver將不會再用來解析該視圖。當定義的全部ViewResolver都不能解析該視圖的時候,Spring就會拋出一個異常。

       基於Spring支持的這種ViewResolver鏈模式,咱們就能夠在SpringMVC應用中同時定義多個ViewResolver,給定不一樣的order值,這樣咱們就能夠對特定的視圖特定處理,以此來支持同一應用中有多種視圖類型。注意:像InternalResourceViewResolver這種能解析全部的視圖,即永遠能返回一個非空View對象的ViewResolver必定要把它放在ViewResolver鏈的最後面。

 

Xml代碼  
  1. <bean class="org.springframework.web.servlet.view.XmlViewResolver">  
  2.    <property name="location" value="/WEB-INF/views.xml"/>  
  3.    <property name="order" value="1"/>  
  4. </bean>  
  5.   
  6. <bean  
  7.    class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
  8.    <property name="prefix" value="/WEB-INF/" />  
  9.    <property name="suffix" value=".jsp" />  
  10.    <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>  
  11. </bean>  
相關文章
相關標籤/搜索