標籤:this async 技術 protected pos control style 主題 mode
運行helloWorld樣本進入調試介面。
DispatcherServlet:前端控制器
DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 945 DispatcherServlet.doService(HttpServletRequest, HttpServletResponse) line: 876 DispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest, HttpServletResponse) line: 931 DispatcherServlet(FrameworkServlet).doGet(HttpServletRequest, HttpServletResponse) line: 822 DispatcherServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 624 DispatcherServlet(FrameworkServlet).service(HttpServletRequest, HttpServletResponse) line: 807 DispatcherServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 731
由上進入源碼查看
DispatcherServlet(FrameworkServlet).service(HttpServletRequest, HttpServletResponse) line: 807
的
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { ...service();}
HttpServletBean 的實現
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {}
接下來重點關注doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = processedRequest != request; // Determine handler for the current request. //1、根據當前請求地址找到哪個處理器來處理請求 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { //2、如果找不到報錯 noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //2\為當前請求確定適配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } try { // Actually invoke the handler. //真正執行方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally { if (asyncManager.isConcurrentHandlingStarted()) { return; } } applyDefaultViewName(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } //處理響應結果 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); return; } // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } }
四步:1)、所有請求進來都經過DispatcherServlet的900:doDispatch()方法(包含了處理請求以及響應的所有流程)2)、916;getHandler(processedRequest);根據當前請求擷取到能處理這個請求的Controller對象3)、923:找到能執行這個Controller對象裡面每一個方法的適配器4)、945:ha.handle適配器調用目標方法(利用反射調用方法)5)、959:轉寄到頁面(處理響應結果)processDispatchResult
1、根據當前請求地址找到哪個處理器來處理請求 mappedHandler = getHandler(processedRequest);
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {for (HandlerMapping hm : this.handlerMappings) {if (logger.isTraceEnabled()) {logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name ‘" + getServletName() + "‘");}HandlerExecutionChain handler = hm.getHandler(request);if (handler != null) {return handler;}}return null;}
SpringfMVC啟動的時候掃描所有的註解,將每一個類的每一個方法能處理什麼請求都已經儲存在handlerMapping中了;DefaultAnnotationHandlerMapping;
2、為當前請求確定適配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
找到能調用這個類裡面每個方法的適配器;適配器利用反射調用方法;
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {for (HandlerAdapter ha : this.handlerAdapters) {if (logger.isTraceEnabled()) {logger.trace("Testing handler adapter [" + ha + "]");}if (ha.supports(handler)) {return ha;}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}
我們都使用註解模式的所以適配器使用第三個;
3、SpringMVC中DispatcherServlet的幾個重要屬性,以及賦值SpringMVC九大組件;
/** MultipartResolver used by this servlet 檔案上傳解析器*/ private MultipartResolver multipartResolver; /** LocaleResolver used by this servlet 國際化解析器*/ private LocaleResolver localeResolver; /** ThemeResolver used by this servlet 主題解析器*/ private ThemeResolver themeResolver; /** List of HandlerMappings used by this servlet 儲存了請求與類的映射關係(哪個請求用哪個類來處理)*/ private List<HandlerMapping> handlerMappings; /** List of HandlerAdapters used by this servlet適配器;用來執行控制器(處理器)目標方法的*/ private List<HandlerAdapter> handlerAdapters; /** List of HandlerExceptionResolvers used by this servlet 異常解析器*/ private List<HandlerExceptionResolver> handlerExceptionResolvers; /** RequestToViewNameTranslator used by this servlet 轉化器*/ private RequestToViewNameTranslator viewNameTranslator; /** FlashMapManager used by this servletFlashMap 管理器 */ private FlashMapManager flashMapManager; /** List of ViewResolvers used by this servlet視圖解析器 */ private List<ViewResolver> viewResolvers;
檔案上傳組件預設沒值;預設賦值;
protected
void initStrategies(ApplicationContext context) { //預設從ioc容器中擷取id為multipartResolver的組件,如果沒有擷取到就賦值為null; initMultipartResolver(context); //按照id擷取localeResolver;如果沒有; initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } //1、有些組件是這麼》?先擷取使用者配置的,如果沒有可以使用預設的(MultipartResolver )//2、有些組件是拿id擷取的;有些是拿類型擷取的,//3、給SpringMVC中配置九大之一的某個組件;如果是拿id‘擷取的?id不要亂寫,用指定id;//如果是用類型擷取,id可以不用寫; 在於DispatcherServlet.class同目錄下有一個properties檔案,這裡封裝了所有組件預設的類型;
SprngMVC源碼學習