// 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; //把request域的所有属性提前保存 if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<>(); Enumeration<?> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); //快照所有属性 } } }
//基本的东西保存到request域中方便处理 Make framework objects available to handlers and view objects. 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());
if (this.flashMapManager != null) { //闪存管理器(重定向携带数据) 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 { 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); } } ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request); } }
//构造出了【目标方法+拦截器整个链路】决定使用哪个Handler处理当前请求 Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { //如果找不到人处理,就send 404 noHandlerFound(processedRequest, response); return; }
//适配器怎么找的、 Determine handler adapter for the current request. 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 (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; }
applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", 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); } } } }
doDispatch处理大流程图
DispatcherServlet#checkMultipart()
protected HttpServletRequest checkMultipart(HttpServletRequest request)throws MultipartException { //使用文件上传解析器来判断是否文件上传请求 if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) { // ...... } // If not returned before: return original request. return request; }
//DispatcherServlet中的九大组件、全是接口,我们完全可以自定义实现。Spring默认也都准备好了这些组件的实现 /** MultipartResolver used by this servlet. */ @Nullable//文件上传解析器 private MultipartResolver multipartResolver;
/** LocaleResolver used by this servlet. */ @Nullable//国际化解析器 Locale(区域信息) private LocaleResolver localeResolver;
/** ThemeResolver used by this servlet. */ @Nullable//主题解析器 private ThemeResolver themeResolver;
/** List of HandlerMappings used by this servlet. */ @Nullable//Handler(处理器、能处理请求的人(Controller))的映射:【保存的就是所有请求都由谁来处理的映射关系】 private List<HandlerMapping> handlerMappings;
/** List of HandlerAdapters used by this servlet. */ @Nullable//Handler处理器的适配器;是一个超级反射工具,帮我们解决参数呀,返回值这些,不需要我们很麻烦的写 private List<HandlerAdapter> handlerAdapters;
/** List of HandlerExceptionResolvers used by this servlet. */ @Nullable//Handler的异常解析器,异常处理功能 private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** RequestToViewNameTranslator used by this servlet. */ @Nullable//把请求转成视图名(我们要跳转的页面地址)的翻译器【没啥用】 private RequestToViewNameTranslator viewNameTranslator;
/** FlashMapManager used by this servlet. */ @Nullable//闪存管理器 private FlashMapManager flashMapManager;
/** List of ViewResolvers used by this servlet. */ @Nullable//视图解析器(我们去哪些页面,怎么过去?) private List<ViewResolver> viewResolvers;
# Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers.
//构造出了【目标方法+拦截器整个链路】决定使用哪个Handler处理当前请求 Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { //如果找不到人处理,就send 404 noHandlerFound(processedRequest, response); return; }
//适配器怎么找的、 Determine handler adapter for the current request. 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 (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; }