SpringMVC重要介面ViewResolver

擊水三千里發表於2019-02-26

SpringMVC用於處理檢視最重要的兩個介面是ViewResolverViewViewResolver的主要作用是把一個邏輯上的檢視名稱解析為一個真

正的檢視,SpringMVC中用於把View物件呈現給客戶端的是View物件本身,而ViewResolver只是把邏輯檢視名稱解析為物件的View

象。View介面的主要作用是用於處理檢視,然後返回給客戶端

這是一個抽象類,這種檢視解析器會把它曾經解析過的檢視儲存起來,然後每次要解析檢視的時候先從快取裡面找,如果找到了對

應的檢視就直接返回,如果沒有就建立一個新的檢視物件,然後把它放到一個用於快取的map中,接著再把新建的檢視返回。使用這

種檢視快取的方式可以把解析檢視的效能問題降到最低

它是對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組成一個RedirectViewRedirectView中將把請求返回的模型屬性組合成查詢引數的形式組合到redirect的URL後面,然後呼叫HttpServletResponse物件的sendRedirect方法進行重定向

<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> 

它是URLBasedViewResolver的子類,所以URLBasedViewResolver支援的特性它都支援。在實際應用中 InternalResourceViewResolver也是使用的最廣泛的一個檢視解析器。

比如 在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在伺服器端跳轉的方式可以很好的解決這個問題。

它繼承自AbstractCachingViewResolver抽象類,所以它也是支援檢視快取的。XmlViewResolver需要給定一個xml配置檔案,該檔案將使用和Spring的bean工廠配置檔案一樣的DTD定義,所以其實該檔案就是用來定義檢視的bean物件的

在該檔案中定義的每一個檢視的bean物件都給定一個名字,然後XmlViewResolver將根據Controller處理器方法返回的邏輯檢視名稱到XmlViewResolver指定的配置檔案中尋找對應名稱的檢視bean用於處理檢視。

該配置檔案預設是/WEB-INF/views.xml件,如果不使用預設值的時候可以在XmlViewResolverlocation屬性中指定它的位 置。XmlViewResolver還實現了Ordered介面,因此我們可以通過其order屬性來指定在ViewResolver鏈中它所處的位置,order的值越小優先順序越高。

這個檢視解析器跟XmlViewResolver有點類似,也是通過把返回的邏輯檢視名稱去匹配定義好的檢視bean物件。 
不同點有二,

一 是BeanNameViewResolver要求檢視bean物件都定義在Spring的application context中,而XmlViewResolver是在指定的配置檔案中尋找檢視bean物件.

二 是BeanNameViewResolver不會進行檢視快取。看一個例子,在SpringMVC的配置檔案中定義了個BeanNameViewResolver檢視解析器和一個id為test的InternalResourceviewbean物件.

<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

它和XmlViewResolver一樣,也是繼承自 AbstractCachingViewResolver,但是它快取的不是檢視,這個會在後面有說到。和XmlViewResolver一樣它也需要有一個配置檔案來定義邏輯檢視名稱和真正的View物件的對應關係,不同的是ResourceBundleViewResolver的配置檔案是一個屬性檔案,而且必須是放在classpath路徑下面的,預設情況下這個配置檔案是在classpath根目錄下的views.properties檔案,如果不使用預設值的話,則可以通過屬性baseNamebaseNames來指定

baseName只是指定一個基名稱,Spring會在指定的classpath根目錄下尋找以指定的baseName開始的屬性檔案進行View解析,如指定的baseName是base,那 麼base.propertiesbaseabc.properties等等以base開始的屬性檔案都會被Spring當做ResourceBundleViewResolver解析檢視的資原始檔。ResourceBundleViewResolver使用的屬性配置檔案的內容類似於這樣:

resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView  
resourceBundle.url=/index.jsp  
test.(class)=org.springframework.web.servlet.view.InternalResourceView  
test.url=/test.jsp 

這兩個檢視解析器都 是UrlBasedViewResolver的子類。FreeMarkerViewResolver會把Controller處理方法返回的邏輯檢視解析為FreeMarkerView,而VolocityViewResolver會把返回的邏輯檢視解析為VolocityView。這兩個檢視解析器類似

FreeMarkerViewResolverVilocityViewResolver都繼承了UrlBasedViewResolver。 對於FreeMarkerViewResolver而言,它會按照UrlBasedViewResolver拼接URL的方式進行檢視路徑的解析。

 

檢視解析器鏈

在SpringMVC中可以同時定義多個ViewResolver檢視解析器,然後它們會組成一個ViewResolver鏈。

當Controller處理器方法返回一個邏輯檢視名稱後,ViewResolver鏈將根據其中ViewResolver的優先順序來進行處理。所有的ViewResolver都實現了Ordered介面,在Spring中實現了這個介面的類都是可以排序的。

ViewResolver中是通過order屬性來指定順序的,預設都是最大值。所以我們可以通過指定ViewResolverorder屬性來實現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鏈的最後面。

相關文章