SpringMVC源碼-執行流程


1. Dispatcher核心執行方法: 

 

2.doDispatcher詳細細節:

  1)、所有請求過來,Dispatcher收到請求;

  2)、調用doDispatcher()方法進行處理;

    》1.getHandler():根據當前請求地址找到能處理這個請求目標處理器類  

        根據當前請求在HandlerMapping找到那個請求的映射信息,獲取到目標處理器類

    》2.getHandlerAdapter():根據當前處理器類獲取到能夠執行這個處理器類的適配器;

        根據當前的處理器類,找到當前類的適配器(HandlerAdapter)

    》3.使用剛才獲取到的適配器執行目標方法;

    》4.目標方法執行完后會返回一個ModelAndView對象;

    》5.將ModelAndView的信息轉發到具體的頁面,然后在請求域中取出ModelAndView中的模型數據;

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;

            try {
          //1.檢查是否為文件上傳請求 processedRequest
= this.checkMultipart(request); multipartRequestParsed = processedRequest != request;
          //2.根據當前的請求地址找到哪個類能來處理 mappedHandler
= this.getHandler(processedRequest);
          //3.如果沒有找到對應的處理器(控制器)來處理這個請求,就報404或拋異常
if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; }           //4.拿到能執行這個類所有方法的適配器(反射工具);
  HandlerAdapter ha
= this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
            
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }           //處理器方法被調用;控制器(Controller)、處理器(Handler)
          //5.適配器來執行目標方法,將目標方法執行完成后的返回值作為視圖名,設置保存到ModelAndView中
          //目標方法無論怎么寫,最終適配器執行完成以后都會將執行后的信息封裝到ModelAndView
mv
= ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; }           //6.如果沒有視圖名,設置一個默認的視圖名 this.applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException("Handler dispatch failed", var21); }        //轉發到目標頁面
       //7.根據方法最終執行完成后封裝的ModelAndView,轉發到對應頁面,而且ModelAndView中的數據可以從請求域中獲取
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); } catch (Exception var22) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); } catch (Throwable var23) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }

3、getHandler()細節:怎么根據當前請求找到那個類來處理  

  》1.getHandler()會返回目標處理器類的執行鏈;

mappedHandler = this.getHandler(processedRequest);

  》2.HandlerMapping:處理器映射,HandlerMappings里面保存了每一個處理器能處理哪些方法的映射信息;

 
         
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            Iterator var2 = this.handlerMappings.iterator();
            while(var2.hasNext()) {
                HandlerMapping mapping = (HandlerMapping)var2.next();
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

4、如何找到目標處理器類 額適配器,要拿適配器去執行目標方法

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            Iterator var2 = this.handlerAdapters.iterator();

            while(var2.hasNext()) {
                HandlerAdapter adapter = (HandlerAdapter)var2.next();
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }

        throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

5、DispatcherServlet中有幾個引用類型的屬性:

  SpringMVC的九大組件:

           SpringMVC在工作的時候,關鍵位置都是由這些組件完成的;共同點:九大組件全部是接口,接口就是規范,提供了非常強大的擴展性;

 /** 文件上傳解析器 */ private MultipartResolver multipartResolver;
/** 區域解析器和國際化有關 */
private LocaleResolver localeResolver;
/** 主題解析器;強大的主題效果切換 */
private ThemeResolver themeResolver;
/** handler映射信息;HandlerMapping */
private List<HandlerMapping> handlerMappings;
/** handler適配器 */
private List<HandlerAdapter> handlerAdapters;
/** SpringMVC強大的異常解析功能:異常解析器 */
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** 請求到視圖名轉換器 */
private RequestToViewNameTranslator viewNameTranslator;
/** FlsahMap+Manager:SpringMVC中進行重定向攜帶數據的功能 */
private FlashMapManager flashMapManager;
/** 視圖解析器 */
private List<ViewResolver> viewResolvers;

  DispatcherServlet中九大組件初始化的地方:服務器啟動就初始化

    組件的初始化:

      去容器中找這個組件,如果沒有找到就用默認配置;有些組件是用類型找的,有些組件使用bean-id找的;

    protected void initStrategies(ApplicationContext context) { this.initMultipartResolver(context); this.initLocaleResolver(context); this.initThemeResolver(context); this.initHandlerMappings(context); this.initHandlerAdapters(context); this.initHandlerExceptionResolvers(context); this.initRequestToViewNameTranslator(context); this.initViewResolvers(context); this.initFlashMapManager(context); }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM