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); }