1. 程式人生 > >Spring MVC 4之ViewResolver檢視解析器

Spring MVC 4之ViewResolver檢視解析器

    所有的We MVC框架都有一套它自己的解析檢視的機制,Spring MVC也不例外,它使用ViewResolver進行檢視解析,讓使用者在瀏覽器中渲染模型。ViewResolver是一種開箱即用的技術,能夠解析JSP、Velocity模板和XSLT等多種檢視。

    Spring處理檢視最重要的兩個介面是ViewResolver和View。ViewResolver介面在檢視名稱和真正的檢視之間提供對映; 而View介面則處理請求將真正的檢視呈現給使用者。

    1.幾種常見的ViewResolver檢視解析器

    在Spring MVC 4控制器中,所有的處理方法必須返回一個邏輯檢視名稱,無論是顯式的(返回String,View或ModelAndView)還是隱式的。Spring中的檢視由檢視解析器處理這個邏輯檢視名稱,Spring有以下幾種檢視解析器:

  AbstractCachingViewResolver:用來快取檢視的抽象檢視解析器。通常情況下,檢視在使用前就準備好了。繼承改解析器就能夠使用檢視快取。

XmlViewResolver :XML檢視解析器。它實現了ViewResolver介面,接受相同DTD定義的XML配置檔案作為Spring的XML bean工廠。

ResourceBundleViewResolver:它使用了ResourceBundle定義下的bean,實現了ViewResolver介面,指定了繫結包的名稱。通常情況下,配置檔案會定義在classpath下的properties檔案中,預設的檔名字是views.properties。

UrlBasedViewResolver:它簡單實現了ViewResolver介面,它不用顯式定義,直接影響邏輯檢視到URL的對映。它讓你不用任何對映就能通過邏輯檢視名稱訪問資源。

InternalResourceViewResolver:國際化檢視解析器。

VelocityViewResolver /FreeMarkerViewResolver:Velocity或FreeMarker檢視解析器。

ContentNegotiatingViewResolver:內容談判檢視解析器

    在JSP檢視技術中,Spring MVC經常會使用 UrlBasedViewResolver檢視解析器,該解析器會將檢視名稱翻譯成URL並通過RequestDispatcher處理請求後渲染檢視。

<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/views/"/>
   <property name="suffix" value=".jsp"/></bean>

    假如我們配置瞭如上所示的URL檢視解析器,我們返回了一個叫“favmvc”的檢視名稱,檢視解析器就會將請求轉發到RequestDispatcher,然後跳轉到/WEB-INF/views/favmvc.jsp頁面。

    假如我們想要在應用中使用不同的檢視技術,我們就應該使用 ResourceBundleViewResolver。

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

    ResourceBundleViewResolver對於每個要處理的檢視,都會檢查 ResourceBundle中basename的唯一性,它使用 [viewname].(class)作為檢視類,[viewname].url作為檢視的url。

    2. 鏈式檢視解析器(Chaining ViewResolvers)

    Spring支援同時配置多個檢視解析器,也就是鏈式檢視解析器。這樣,在某些情況下,就能夠重寫某些檢視。如果我們配置了多個檢視解析器,並想要給檢視解析器排序的話,設定 order 屬性就可以指定解析器執行的順序。order的值越高,解析器執行的順序越晚。

    下面程式碼所示的例子由兩個檢視解析器組成。 InternalResourceViewResolver總是最後一個執行,而 XmlViewResolver則指定解析XML檢視(InternalResourceViewResolver不支援Excel檢視)。

<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
   <property name="prefix" value="/WEB-INF/jsp/"/>
   <property name="suffix" value=".jsp"/></bean><bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
   <property name="order" value="1"/>
   <property name="location" value="/WEB-INF/views.xml"/></bean><!-- in views.xml --><beans>
   <bean name="report" class="org.springframework.example.ReportExcelView"/></beans>

    如果檢視解析器沒有指定檢視的話,Spring就會檢查其它的檢視解析器,直到有一個完整的包含檢視的檢視解析器。如果一個完整的檢視解析器也沒有找到的話,Spring就會丟擲 ServletException。

    檢視解析器規定如果沒有找到檢視就返回null。但不是所有的檢視解析器都這麼做,因為在某些情況下,解析器並不能檢測是否存在檢視。比如InternalResourceViewResolver在內部使用RequestDispatcher時,排程轉發是判斷JSP是否存在的唯一方法,但該action卻只能執行一次。VelocityViewResolver和其它的一些解析器也這樣,區分這些檢視解析器能否在找不到檢視的情況下返回null,最好的方法就是看官方文件中它是否支援了。由於 InternalResourceViewResolver總會返回檢視,在檢視鏈中使用InternalResourceViewResolver就能讓你避免這些問題。

    3.  重定向檢視

    在controller控制器中強制重定向的方法就是建立並返回Spring的RedirectView例項。在這種情況下,DispatcherServlet不再使用正常的檢視機制,因為它已經返回了重定向檢視,DispatcherServlet只是告訴檢視去顯示。

    RedirectView會呼叫 HttpServletResponse.sendRedirect()方法,然後它就作為HTTP重定向返回給客戶端瀏覽器。預設情況下,所有的模板屬性變數都認為是重定向URL,其餘的屬性自動附加為查詢引數。

    redirect字首

    儘管RedirectView工作機制很好,但如果控制器本身建立RedirectView時,毫無疑問控制器本身知道該如何重定向。這樣做並不好,控制器不應該關心響應如何處理,它只是處理被注入的檢視名稱。

    當我們在返回檢視名稱時,如果使用了“redirect:”字首(如“redirect : /login”),UrlBasedViewResolver檢視控制器會識別這是一次特殊的重定向,並把redirect後面的檢視名稱當做重定向的地址。

    假如我們在http://favccxx.com應用中返回“redirect:/favboy”檢視時, 系統會重定向到http://favccxx.com/favboy。但如果我們返回了“redirect:http://favsoft.me”這樣的檢視時,系統會重定向到http://favsoft.me的檢視上。

    forward字首

    forward字首檢視是另一種通過URLBasedViewResolver機制處理到的轉向機制,它在檢視名稱周圍建立InternalResourceView,因此這個字首跟InternalResourceViewResolver和InternalResourceView無關。但這個字首在你想使用其它檢視技術但想強制通過Servlet/JSP引擎處理資源進行轉向時是有用的。

    redirect與forward的區別    

    redirect方式相當 於"response.sendRedirect()".這種方式外部特徵就是瀏覽器位址列最後顯示的路徑是轉發後的新的路徑.工作方式是這樣的,伺服器端會首先發一個response給瀏覽器,然後瀏覽器收到這個response後再發一個requeset給伺服器,然後伺服器發新的response給瀏覽器。這時頁面收到的request是一個新從瀏覽器發來的.這種方式的結果是:

    A.在轉發前後有兩個不同的request物件,轉發前後的兩個控制器在request上的引數(request.getParameter())和request屬性(request.getAttribute())不能共享。

    B.如果轉發前後的兩個控制器都配置在spring 攔截器範圍內,這樣攔截器會攔截前後兩個request,即會攔截兩次。

    C.最後返回到瀏覽器後,因為位址列顯示的是轉發後的url,所以重新整理頁面時只會執行後面的url對映的控制器。

    forward方式相當於 request.getRequestDispatcher().forward(request,response) .這種方式的外部特徵是瀏覽器地址顯示的路徑是轉發前的路徑。工作方式是這樣,forward 發生在伺服器內部,在前一個控制器處理完畢後,直接進入下一個控制器處理,並將最後的response發給瀏覽器。這種方式的結果是:

    A.轉發前後是同一個request,後一個控制器可共享前一個控制器的引數與屬性。

    B.因為是同一個request,攔截器只會攔截前一個url,如果前一個url在對映時未配置到攔截器攔截,則攔截後一個url,即只攔截一次。

    C.最後返回到瀏覽器後,因為位址列顯示的是轉發前的url,所以重新整理頁面時會依次執行前後兩個控制器。

   總結:本文介紹了Spring MVC 4中常見的幾種檢視解析器,以及如何配置檢視解析器包括鏈式檢視解析器,最後除了正常檢視對映機制外,我們還能夠通過redirect/forward檢視轉向機制完成檢視的重定向。本文偏向原理性介紹,關於檢視解析機制在工作中的使用,並沒有做過多的介紹,目的是讓讀者能夠了解ViewResolver的工作機制。