1. 程式人生 > >SpringMVC專題——SpringMVC的流程(個人理解)

SpringMVC專題——SpringMVC的流程(個人理解)

        SpringMVC處理請求:

——》訪問URL首先被DispatcherServlet截獲

——》DispatcherServlet通過handlerMapping【定位controller,本質map<url,controller>】獲得HandlerExecutionChain

——》然後獲得HandlerAdapter【定位方法】(Spring容器注入argumentResolvers(List中都實現了HandlerMethodArgumentResolver)和returnValueHandlers(List中都實現了HandlerMethodReturnValueHandler)兩個屬性,前者有很多Resolver或者Processor處理請求,後者有很多handler或者processor處理響應

——》建立ServletInvocableHandlerMethod物件(分兩部分處理請求和響應,此時通過HandlerAdapter的注入argumentResolvers和returnValueHandlers

——》形參的注入

(例子1:@RequestBody註解,此時呼叫argumentResolvers中的RequestResponseBodyMethodProcessor進行處理,RequestResponseBodyMethodProcessor中構造方法中傳入了List<HttpMessageConverter<?>>,List<HttpMessageConverter<?>>包含了很多訊息轉換器,【例如StringHttpMessageConverter類,它的canRead()方法返回true,然後它的read()方法會從請求中讀出請求引數,繫結到XXX方法的string變數中

等等】,然後RequestResponseBodyMethodProcessor根據http請求頭部的contentType然後選擇合適的訊息轉換器進行讀取

(例子2:@RequestParam註解,先是呼叫argumentResolvers中的RequestParamMethodArgumentResolver進行處理,在處理引數的時候使用request.getParameter(引數名),如果為null,RequestParamMethodArgumentResolver處理missing value會觸發MissingServletRequestParameterException異常,否則最後通過DataBinder找到合適的屬性編輯器進行型別轉換

(例子3:形參上沒有註解,如果是簡單型別【String,Integer等等】此時呼叫argumentResolvers中RequestParamMethodArgumentResolver處理,如果是非簡單型別【自定義物件等等】,此時呼叫argumentResolvers中ServletModelAttributeMethodProcessor【引數型別是實現或繼承或是WebRequest、ServletRequest、MultipartRequest、HttpSession、Principal、Locale、TimeZone、InputStream、Reader、HttpMethod這些類,所以我們能再Controller中新增一個HttpServletRequest引數,Spring會為我們自動獲得HttpServletRequest物件的原因】,最後通過DataBinder例項化物件,並寫入對應的屬性

——》執行方法內容,呼叫業務處理等等

——》如果有使用@ResponseBody註解的話,此時會呼叫returnValueHandlers中的RequestResponseBodyMethodProcessor,RequestResponseBodyMethodProcessor構造方法中傳入了List<HttpMessageConverter<?>>,RequestResponseBodyMethodProcessor呼叫handleReturnValue,響應的具體處理是使用訊息轉換器。

——》方法執行完畢後,向DispatcherServlet 返回一個ModelAndView物件

——》根據返回的ModelAndView,選擇一個適合的ViewResolver(必須是已經註冊到Spring容器中的ViewResolver)返回給DispatcherServlet

——》將渲染結果返回給客戶端



以下是轉載別人總結的HandlerMethodArgumentResolver實現類(處理請求)的作用和returnValueHandlers實現類(處理響應)的作用


1. RequestParamMethodArgumentResolver


 支援帶有@RequestParam註解的引數或帶有MultipartFile型別的引數


2. RequestParamMapMethodArgumentResolver


  支援帶有@RequestParam註解的引數 && @RequestParam註解的屬性value存在 && 引數型別是實現Map介面的屬性


3. PathVariableMethodArgumentResolver


支援帶有@PathVariable註解的引數 且如果引數實現了Map介面,@PathVariable註解需帶有value屬性


4. MatrixVariableMethodArgumentResolver


支援帶有@MatrixVariable註解的引數 且如果引數實現了Map介面,@MatrixVariable註解需帶有value屬性 


5. RequestResponseBodyMethodProcessor


支援的請求型別是Controller方法引數中帶有@RequestBody註解,支援的響應型別是Controller方法帶有@ResponseBody註解


6. ServletRequestMethodArgumentResolver


 引數型別是實現或繼承或是WebRequest、ServletRequest、MultipartRequest、HttpSession、Principal、Locale、TimeZone、InputStream、Reader、HttpMethod這些類。


(這就是為何我們在Controller中的方法裡新增一個HttpServletRequest引數,Spring會為我們自動獲得HttpServletRequest物件的原因)


7. ServletResponseMethodArgumentResolver


 引數型別是實現或繼承或是ServletResponse、OutputStream、Writer這些類


8. RedirectAttributesMethodArgumentResolver


 引數是實現了RedirectAttributes介面的類


9. HttpEntityMethodProcessor


 引數型別是HttpEntity


從名字我們也看的出來, 以Resolver結尾的是實現了HandlerMethodArgumentResolver介面的類,以Processor結尾的是實現了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler的類。