類關係java
DispatcherServlet 繼承 FrameworkServlet 繼承 HttpServletBean,HttpServletBean 是一個HttpServlet和EnvironmentCapable, EnvironmentAware接口的實現。web
本章關注點在DispatcherServlet對請求的分派調用流程上,這些類暫不關注。spring
成員變量json
一、靜態變量主要是一些bean名稱,以及request attribute 的key。如app
/** Well-known name for the MultipartResolver object in the bean factory for this namespace. */ public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; /** Well-known name for the LocaleResolver object in the bean factory for this namespace. */ public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; /** Well-known name for the ThemeResolver object in the bean factory for this namespace. */ public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
二、具體的特殊的bean,上一章中提到的特殊bean。如async
/** 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;
方法ide
方法重點關注doService,doDispatch這兩個方法,其餘的方法是get/set 和初始化方法,不是本章的關注對象。下面的這兩個方法源碼和註釋。post
//重寫HttpServlet 的請求處理方法 @Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } // Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. //保留一個原請求屬性的備份。 Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { //是內部發出的請求 forward attributesSnapshot = new HashMap<String, Object>(); Enumeration<?> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); //若是是DispatcherServlet cleanupAfterInclude(是include 請求就清理)屬性爲true,或者request的屬性是DispatcherServlet附加的,保存備份 if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } //附加webApplicationContext 的特殊bean // Make framework objects available to handlers and view objects. //web application context request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); //國際化 request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); //主題 request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); //??? request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); //閃存,重定向時能夠不攜帶參數 FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { //分派到handler,進行業務邏輯處理 doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } } 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 { //檢查是否 multipart request processedRequest = checkMultipart(request); //request 不等於 processedRequest 表示檢查到multi ,並構建返回 multi request multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. //決定、判斷、獲取 handler mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { //找不到相應的handler ,返回並提示 noHandlerFound noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //查找handler 的適配器(不一樣的方法細節多樣、參數等,經過adapter 封裝) HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. //判斷是否支持last-modified String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //執行前攔截器 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. //調用實際業務方法邏輯 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //解析modelview 中的名稱映射對應的視圖模板。 applyDefaultViewName(processedRequest, 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 if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
註釋不正確的地方,請指出。this
從源碼咱們能夠看出,基本上請求的出來流程正如第一篇中所描述的。spa
第一步是綁定各類各樣的web context bean。
第二步是搜索獲取對應請求的處理handler,以及對應的adapter。
第三步是執行找出的handler,前攔截器,handler, 後攔截器。
第四步是將結果或異常進行處理,如將string 映射到具體的view 或者輸出json等。捕獲異常的調用Exception handler 處理。