<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 前言 本章將分析SpringMVC的視圖這部分內容,讓讀者了解SpringMVC視圖的設計原理。 # 重要接口和類介紹 1.**View接口** 視圖基礎接口,它的各種實現類是無狀態的,因此是線程安全的。 該接口定義了兩個方法: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver01.png) 2.**AbstractView抽象類** View接口的基礎實現類。我們稍微介紹一下這個抽象類。 首先看下這個類的屬性: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver02.png) 再看下抽象類中接口方法的實現: getContentType方法直接返回contentType屬性即可。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver03.png) render方法: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver04.png) 3.**AbstractUrlBasedView抽象類** 繼承自AbstractView抽象類,增加了1個類型為String的url參數。 4.**InternalResourceView類** 繼承自AbstractUrlBasedView抽象類的類,表示JSP視圖。 我們看下這個類的renderMergedOutputModel方法(AbstractView抽象類定義的抽象方法,為View接口提供的render方法服務)。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver05.png) 5.**JstlView類** JSTL視圖,繼承自InternalResourceView,該類大致上與InternalResourceView類一致。 6.**AbstractTemplateView抽象類** 繼承自AbstractUrlBasedView抽象類,重寫了renderMergedOutputModel方法,在該方法中會調用renderMergedTemplateModel方法,renderMergedTemplateModel方法為新定義的抽象方法。 該抽象類有幾個boolean屬性exposeSessionAttributes,exposeRequestAttributes。設置為true的話會將request和session中的鍵值和值丟入到renderMergedTemplateModel方法中的model這個Map參數中。 這個類是某些模板引擎視圖類的父類。 比如FreemarkerView,VelocityView。 7.**FreeMarkerView類** 繼承自AbstractTemplateView抽象類。 直接看renderMergedTemplateModel方法,renderMergedTemplateModel內部會調用doRender方法: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver06.png) 8.**RedirectView類** 繼承自AbstractUrlBasedView,并實現SmartView接口。SmartView接口定義了1個boolean isRedirectView();方法。 該視圖的renderMergedOutputModel方法主要就是通過response.sendRedirect進行重定向。 9.**ViewResolver接口** 視圖解釋器,用來解析視圖View,與View接口配合使用。 該接口只有1個方法,通過視圖名稱viewName和Locale對象得到View接口實現類: View resolveViewName(String viewName, Locale locale) throws Exception; 10.**AbstractCachingViewResolver抽象類** 帶有緩存功能的ViewResolver接口基礎實現抽象類,該類有個屬性名為viewAccessCache的以 "viewName_locale" 為key, View接口為value的Map。 該抽象類實現的resolveViewName方法內部會調用createView方法,方法內部會調用loadView抽象方法。 11.**UrlBasedViewResolver類** 繼承自AbstractCachingViewResolver抽象類、并實現Ordered接口的類,是ViewResolver接口簡單的實現類。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver07.png) 該類復寫了createView方法: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver08.png) 父類(AbstractCachingViewResolver)的createView方法內部會調用loadView抽象方法,UrlBasedViewResolver實現了這個抽象方法: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver09.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver10.png) 下面對UrlBasedViewResolver做1個test,配置如下: <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/> <property name="viewNames"> <array> <value type="java.lang.String">*</value> </array> </property> <property name="contentType" value="text/html;charset=utf-8"/> <property name="attributesMap"> <map> <entry key="mytest" value="mytestvalue"/> </map> </property> <property name="attributes"> <props> <prop key="test">testvalue</prop> </props> </property> </bean> 我們看到:以InternalResourceView這個JSP視圖作為視圖;viewNames我們設置了*,這里的*代表全部視圖名(這個viewNames屬性不設置也可以,代表全部視圖名都處理);http響應頭部contentType信息:text/html;charset=utf-8;attributesMap和attributes傳入的Map和Properties參數都會被丟入到staticAttributes屬性中,這個staticAttributes會被設置成AbstractView的staticAttributes屬性,也就是request域中的參數。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver11.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver12.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver13.png) 我們看到request域中沒有設置mytest和testvalue值。但是頁面中會顯示,因為我們配置了attributesMap和attributes參數。 如果我們把viewNames中的"*"改成"index1"。那么就報錯了,因為處理視圖名的時候index匹配不上index1。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver14.png) 12.**InternalResourceViewResolver類** 繼承自UrlBasedViewResolver,以InternalResourceView作為視圖,若項目中存在“javax.servlet.jsp.jstl.core.Config”該類,那么會以JstlView作為視圖。重寫了buildView方法,主要就是為了給InternalResourceView視圖設置屬性。 13.**AbstractTemplateViewResolver類** 繼承自UrlBasedViewResolver,重寫了buildView方法,主要就是構造AbstractTemplateView以及為它設置相應的屬性。 14.**FreeMarkerViewResolver類** 繼承自AbstractTemplateViewResolver,將視圖設置為FreeMarkerView。 15.**ModelAndView對象** 顧名思義,帶有視圖和Model屬性的一個模型和視圖類。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver15.png) **值得注意的是,這個視圖屬性是一個Object類型的數據,可以直接是View接口的實現類或者視圖名(字符串)。** # 源碼分析 下面我們來分析SpringMVC處理視圖的源碼。 SpringMVC在處理請求的時候,通過RequestMappingHandlerMapping得到HandlerExecutionChain,然后通過RequestMappingHandlerAdapter得到1個ModelAndView對象,之后通過processDispatchResult方法處理。 processDispatchResult方法如下: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver16.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver17.png) 如果配置的ViewResolver如下: <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> 那么就是使用InternalResourceViewResolver來解析視圖。 之前分析過,InternalResourceViewResolver重寫了UrlBasedViewResolver的buildView方法。但是還是會調用UrlBasedViewResolver的buildView方法。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver18.png) 最終得到InternalResourceView或JstlView視圖。這兩個視圖的render方法本章介紹重要接口及類的時候已分析。 PS:DispathcerServlet中的viewResolvers屬性是個集合,如果存在多個ViewResolver對象,必定會有優先級的問題,這部分的內容請參考[Spring中Ordered接口簡介](spring/Spring-Ordered-interface.md) # 編碼自定義的ViewResolver 下面,我們就來編寫自定義的ViewResolver。 自定義的ViewResolver處理視圖名的時候,遇到 "jsp:" 開頭的會找jsp頁面,遇到 "freemarker:" 開頭的找freemarker頁面。 public class CustomViewResolver extends UrlBasedViewResolver { public static final String JSP_URL_PREFIX = "jsp:"; public static final String FTL_URL_PREFIX = "freemarker:"; private static final boolean jstlPresent = ClassUtils.isPresent( "javax.servlet.jsp.jstl.core.Config", CustomViewResolver.class.getClassLoader()); private Boolean exposePathVariables = false; private boolean exposeRequestAttributes = false; private boolean allowRequestOverride = false; private boolean exposeSessionAttributes = false; private boolean allowSessionOverride = false; private boolean exposeSpringMacroHelpers = true; public CustomViewResolver() { this.setViewClass(FreeMarkerView.class); } @Override protected AbstractUrlBasedView buildView(String viewName) throws Exception { if(viewName.startsWith(FTL_URL_PREFIX)) { return buildFreemarkerView(viewName.substring(FTL_URL_PREFIX.length())); } else if(viewName.startsWith(JSP_URL_PREFIX)) { Class viewCls = jstlPresent ? JstlView.class : InternalResourceView.class; return buildView(viewCls, viewName.substring(JSP_URL_PREFIX.length()), getPrefix(), ".jsp"); } else { //默認以freemarker處理 return buildFreemarkerView(viewName); } } private AbstractUrlBasedView build(Class viewClass, String viewName, String prefix, String suffix) { AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(viewClass); view.setUrl(prefix + viewName + suffix); String contentType = getContentType(); if (contentType != null) { view.setContentType(contentType); } view.setRequestContextAttribute(getRequestContextAttribute()); view.setAttributesMap(getAttributesMap()); if (this.exposePathVariables != null) { view.setExposePathVariables(exposePathVariables); } return view; } private AbstractUrlBasedView buildFreemarkerView(String viewName) throws Exception { AbstractTemplateView view = (AbstractTemplateView) build(FreeMarkerView.class, viewName, "", getSuffix()); view.setExposeRequestAttributes(this.exposeRequestAttributes); view.setAllowRequestOverride(this.allowRequestOverride); view.setExposeSessionAttributes(this.exposeSessionAttributes); view.setAllowSessionOverride(this.allowSessionOverride); view.setExposeSpringMacroHelpers(this.exposeSpringMacroHelpers); return view; } //get set方法省略 } xml配置: <bean class="org.format.demo.support.viewResolver.CustomViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".ftl"/> <property name="contentType" value="text/html;charset=utf-8"/> <property name="exposeRequestAttributes" value="true"/> <property name="exposeSessionAttributes" value="true"/> <property name="exposeSpringMacroHelpers" value="true"/> <property name="requestContextAttribute" value="request"/> </bean> <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/view/"/> <property name="defaultEncoding" value="utf-8"/> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">10</prop> <prop key="locale">zh_CN</prop> <prop key="datetime_format">yyyy-MM-dd</prop> <prop key="date_format">yyyy-MM-dd</prop> <prop key="number_format">#.##</prop> </props> </property> </bean> 簡單解釋一下:CustomViewResolver解析視圖名的時候,判斷 "jsp:" 和 "freemarker:" 開頭的名字,如果是 "jsp:" 開頭的,如果有JSTL依賴,構造JSTLView視圖,否則構造InternalResourceView視圖。如果是 "freemarker:" 構造FreemarkerView。在構造視圖之前分別會設置一些屬性。 xml配置:配置prefix是為了給jsp視圖用的,freemarker視圖不需要prefix,因為FreemarkerView內部會使用配置的FreeMarkerConfigurer,并用FreeMarkerConfigurer內部的templateLoaderPath屬性作為前綴,配置的suffix是為了讓FreemarkerView使用,當后綴。 最后附上Controller代碼: @Controller @RequestMapping(value = "/tvrc") public class TestViewResolverController { @RequestMapping("jsp") public ModelAndView jsp(ModelAndView view) { view.setViewName("jsp:trvc/index"); return view; } @RequestMapping("/ftl") public ModelAndView freemarker(ModelAndView view) { view.setViewName("freemarker:trvc/index"); return view; } } 視圖 /WEB-INF/view/trvc/index.jsp 中的的內容是輸出This is jsp page 視圖 /WEB-INF/view/trvc/index.ftl 中的的內容是輸出This is freemarker page ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver19.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-view-viewResolver20.png) # 總結 本章分析了SpringMVC中的視圖機制,View和ViewResolver這兩個接口是視圖機制的核心,并分析了幾個重要的View和ViewResolver接口實現類,最終寫了一個區別jsp和freemarker視圖的ViewResolver實現類,讓讀者更加理解視圖機制。 希望這篇文章能幫助讀者了解SpringMVC視圖機制。 # 參考資料 [http://my.oschina.net/HeliosFly/blog/221392](http://my.oschina.net/HeliosFly/blog/221392)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看