一、ViewResolver
根據視圖的名稱將其解析為 View 類型的視圖,如通過 ModelAndView 中的視圖名稱將其解析成 View,View 是用來渲染頁面的,也就是將 Model 填入模板中,生成 html 或其他格式的文件。
可以設置多個解析策略,如可以根據 JSP 來解析,或者按照 Velocity 模版解析,如果設置了多個解析策略則可以通過 order 屬性來設定其優先級,數值越小優先級越高,前面的視圖解析器解析后就不會讓后面的繼續解析。默認的解析策略是 InternalResourceViewResolver,按照 JSP 頁面來解析。ViewResolver 接口中的方法如下:
- View resolveViewName(String viewName, Locale locale);
1 帶有緩存的 ViewResolver
AbstractCachingViewResolver 是帶有緩存的 ViewResolver,它每次解析時先從緩存里查找,如果找到視圖就返回,沒有就創建新的視圖,且創建新視圖的方法由其子類實現,具體代碼如下所示:
@Override public View resolveViewName(String viewName, Locale locale) throws Exception { // 是否啟用緩存,可通過setCache()方法或setCacheLimit()方法開啟緩存,是一個ConcurrentHashMap,默認緩存大小1024 if (!isCache()) { return createView(viewName, locale); } else { // 得到 view 在緩存中的 key 值 Object cacheKey = getCacheKey(viewName, locale); View view = this.viewAccessCache.get(cacheKey); // 如果沒有找到 view 則創建,采用雙重校驗的方式進行安全創建 if (view == null) { synchronized (this.viewCreationCache) { view = this.viewCreationCache.get(cacheKey); if (view == null) { // 具體的創建方式由子類實現 view = createView(viewName, locale); if (view == null && this.cacheUnresolved) { view = UNRESOLVED_VIEW; } if (view != null) { this.viewAccessCache.put(cacheKey, view); this.viewCreationCache.put(cacheKey, view); } } } } return (view != UNRESOLVED_VIEW ? view : null); } }
1.1 ResourceBundleViewResolver
ResourceBundleViewResolver 根據 views.properties 文件來解析視圖,這個文件位於 classpath 路徑下,使用方式如下:
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <!-- 設定屬性文件名為views --> <property name="basename" value="views"></property> </bean>
1.2 XmlViewResolver
XmlViewResolver 根據 xml 文件來解析視圖,使用方式如下:
<bean class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="location"> <value>/WEB-INF/spring-views.xml</value> </property> </bean>
1.3 UrlBasedViewResolver
UrlBasedViewResolver 提供了拼接 URL 的方式來解析視圖,通過 prefix 屬性拼接一個前綴,通過 suffix 屬性拼接一個后綴,就得到了視圖的 URL。還可以加入 redirect: 與 forword: 前綴,使用 redirect: 前綴會調用 HttpServletResponse對象的 sendRedirect() 方法進行重定向,使用 forword: 前綴會利用 RequestDispatcher的forword 方式跳轉到指定的地址。另外,使用時還要指定 viewClass 屬性,表示要解析成哪種 View,的使用方式如下:
<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>
1.4 InternalResourceViewResolver
InternalResourceViewResolver 是 UrlBasedViewResolver 的子類,將 InternalResourceView 作為默認的 View 類,但如果當前classpath 中有 jstl 的 jar 包時則使用 JstlView 作為 view 來渲染。
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
2 其他的 ViewResolver
2.1 BeanNameViewResolver
BeanNameViewResolver 是通過視圖名稱去容器中獲取對應的 view 對像,所以在使用前需要將 view 對象注冊到容器中。它沒有緩存,實現方式如下:
@Override public View resolveViewName(String viewName, Locale locale) throws BeansException { ApplicationContext context = getApplicationContext(); if (!context.containsBean(viewName)) { // Allow for ViewResolver chaining... return null; } if (!context.isTypeMatch(viewName, View.class)) { // Since we're looking into the general ApplicationContext here, // let's accept this as a non-match and allow for chaining as well... return null; } return context.getBean(viewName, View.class); }
(未完成)