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變數中
(例子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的類。