说在前面java
本次主要介绍DispatcherServlet组件,更多精彩请关注”天河聊架构“微信公众号。ios
springmvc配置解析web
进入到这个方法org.springframework.web.servlet.FrameworkServlet#servicespring
@Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { // 执行request请求 processRequest(request, response); } else { super.service(request, response); } }
进入到这个方法org.springframework.web.servlet.FrameworkServlet#processRequest跨域
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); // 获取请求绑定属性 -》 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); // 获取异步请求管理器 -》 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); // 注册callable返回值拦截器 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor()); // 初始化上下文 initContextHolders(request, localeContext, requestAttributes); try { // 执行request请求模板方法 -》 doService(request, response); } catch (ServletException ex) { failureCause = ex; throw ex; } catch (IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally { resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { // -》 requestAttributes.requestCompleted(); } if (logger.isDebugEnabled()) { if (failureCause != null) { this.logger.debug("Could not complete request", failureCause); } else { if (asyncManager.isConcurrentHandlingStarted()) { logger.debug("Leaving response open for concurrent processing"); } else { this.logger.debug("Successfully completed request"); } } } // 发布请求处理事件 -》 publishRequestHandledEvent(request, response, startTime, failureCause); } }
进入到这个方法org.springframework.web.context.request.RequestContextHolder#getRequestAttributes微信
public static RequestAttributes getRequestAttributes() { RequestAttributes attributes = requestAttributesHolder.get(); if (attributes == null) { attributes = inheritableRequestAttributesHolder.get(); } return attributes; }
往上返回到这个方法org.springframework.web.context.request.async.WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)架构
public static WebAsyncManager getAsyncManager(ServletRequest servletRequest) { WebAsyncManager asyncManager = null; // 从request中获取请求管理器 Object asyncManagerAttr = servletRequest.getAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE); if (asyncManagerAttr instanceof WebAsyncManager) { asyncManager = (WebAsyncManager) asyncManagerAttr; } // 若是没有就建立后绑定到request中 if (asyncManager == null) { asyncManager = new WebAsyncManager(); servletRequest.setAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE, asyncManager); } return asyncManager; }
进入到这个方法org.springframework.web.servlet.DispatcherServlet#doServicemvc
@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; //为include请求保存了一个参数map快照 // 若是是include请求 if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<String, Object>(); // 获取请求参数 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)); } } } // 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()); 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); } } } }
进入到这个方法org.springframework.web.servlet.DispatcherServlet#doDispatchapp
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. 获取请求的handler -》 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { // 找不到handler报错 -》 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 (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.执行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); } } } }
进入到这个方法org.springframework.web.servlet.DispatcherServlet#checkMultipartcors
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException { // 判断是不是上传文件请求 -》 if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) { if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) { logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " + "this typically results from an additional MultipartFilter in web.xml"); } else if (hasMultipartException(request) ) { logger.debug("Multipart resolution failed for current request before - " + "skipping re-resolution for undisturbed error rendering"); } else { try { // 解析文件上传 -》 return this.multipartResolver.resolveMultipart(request); } catch (MultipartException ex) { if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) { logger.debug("Multipart resolution failed for error dispatch", ex); // Keep processing error dispatch with regular request handle below } else { throw ex; } } } } // If not returned before: return original request. return request; }
进入到这个方法org.springframework.web.multipart.support.StandardServletMultipartResolver#isMultipart
@Override public boolean isMultipart(HttpServletRequest request) { // Same check as in Commons FileUpload... 若是不是post请求直接返回 if (!"post".equalsIgnoreCase(request.getMethod())) { return false; } // 请求资源类型中是否包含multipart/ String contentType = request.getContentType(); return StringUtils.startsWithIgnoreCase(contentType, "multipart/"); }
这种是springmvc标准实现,另外一种是common uploiad实现。
往上返回到这个方法org.springframework.web.multipart.support.StandardServletMultipartResolver#resolveMultipart
@Override public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException { return new StandardMultipartHttpServletRequest(request, this.resolveLazily); }
这种是springmvc标准实现。
往上返回到这个方法org.springframework.web.multipart.commons.CommonsMultipartResolver#resolveMultipart
@Override public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException { Assert.notNull(request, "Request must not be null"); if (this.resolveLazily) { return new DefaultMultipartHttpServletRequest(request) { @Override // 解析上传文件请求 -》 protected void initializeMultipart() { MultipartParsingResult parsingResult = parseRequest(request); setMultipartFiles(parsingResult.getMultipartFiles()); setMultipartParameters(parsingResult.getMultipartParameters()); setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes()); } }; } else { MultipartParsingResult parsingResult = parseRequest(request); return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(), parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes()); } }
这种是common upload实现。
进入到这个方法org.springframework.web.multipart.commons.CommonsMultipartResolver#parseRequest
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { // 获取请求的编码 -》 String encoding = determineEncoding(request); // 准备上传 -》 FileUpload fileUpload = prepareFileUpload(encoding); try { // 处理上传请求 List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request); // 解析上传文件 return parseFileItems(fileItems, encoding); } catch (FileUploadBase.SizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); } catch (FileUploadBase.FileSizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex); } catch (FileUploadException ex) { throw new MultipartException("Failed to parse multipart servlet request", ex); } }
进入到这个方法org.springframework.web.multipart.commons.CommonsMultipartResolver#determineEncoding
protected String determineEncoding(HttpServletRequest request) { String encoding = request.getCharacterEncoding(); if (encoding == null) { encoding = getDefaultEncoding(); } return encoding; }
往上返回到这个方法org.springframework.web.multipart.commons.CommonsFileUploadSupport#prepareFileUpload
protected FileUpload prepareFileUpload(String encoding) { FileUpload fileUpload = getFileUpload(); FileUpload actualFileUpload = fileUpload; // Use new temporary FileUpload instance if the request specifies 若是请求指定,则使用新的临时FileUpload实例 // its own encoding that does not match the default encoding.不匹配默认编码的自身编码。 if (encoding != null && !encoding.equals(fileUpload.getHeaderEncoding())) { actualFileUpload = newFileUpload(getFileItemFactory()); actualFileUpload.setSizeMax(fileUpload.getSizeMax()); // 文件上传文件最大值 actualFileUpload.setFileSizeMax(fileUpload.getFileSizeMax()); actualFileUpload.setHeaderEncoding(encoding); } return actualFileUpload; }
往上返回到这个方法org.springframework.web.servlet.DispatcherServlet#getHandler
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() + "'"); } // 获取request的handler执行链 -》 HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
进入到这个方法org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
@Override public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 根据请求找到hander -》 Object handler = getHandlerInternal(request); if (handler == null) { // 若是找不到handler就使用默认的handler handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; // 从上下文中获取handler handler = getApplicationContext().getBean(handlerName); } // 根据handler和request获取执行链 拦截器和要执行的handler -》 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 若是是跨域请求,header中有Origin -》 if (CorsUtils.isCorsRequest(request)) { // 根据请求获取跨域配置信息 -》 CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); // 根据handler和request获取跨域配置 -》 CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); // 获取跨域请求的执行链 -》 executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
进入到这个方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal
@Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 根据请求路径匹配到业务hander方法的路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); if (logger.isDebugEnabled()) { logger.debug("Looking up handler method for path " + lookupPath); } this.mappingRegistry.acquireReadLock(); try { // 匹配业务handler方法 -》 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); if (logger.isDebugEnabled()) { if (handlerMethod != null) { logger.debug("Returning handler method [" + handlerMethod + "]"); } else { logger.debug("Did not find handler method for [" + lookupPath + "]"); } } return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }
进入到这个方法org.springframework.web.util.UrlPathHelper#getLookupPathForRequest
public String getLookupPathForRequest(HttpServletRequest request) { // Always use full path within current servlet context? 老是在当前servlet上下文中使用完整路径? -》 if (this.alwaysUseFullPath) { return getPathWithinApplication(request); } // Else, use path within current servlet mapping if applicable 不然,在当前servlet映射中使用path(若是适用) String rest = getPathWithinServletMapping(request); if (!"".equals(rest)) { return rest; } else { return getPathWithinApplication(request); } }
进入到这个方法org.springframework.web.util.UrlPathHelper#getPathWithinApplication
public String getPathWithinApplication(HttpServletRequest request) { // 获取servlet上下文路径 -》 String contextPath = getContextPath(request); // 获取资源请求路径 -》 String requestUri = getRequestUri(request); String path = getRemainingPath(requestUri, contextPath, true); if (path != null) { // Normal case: URI contains context path. return (StringUtils.hasText(path) ? path : "/"); } else { return requestUri; } }
进入到这个方法org.springframework.web.util.UrlPathHelper#getContextPath
public String getContextPath(HttpServletRequest request) { // 获取servlet上下文路径 String contextPath = (String) request.getAttribute(WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE); if (contextPath == null) { contextPath = request.getContextPath(); } if ("/".equals(contextPath)) { // Invalid case, but happens for includes on Jetty: silently adapt it. contextPath = ""; } // 解码请求 -》 return decodeRequestString(request, contextPath); }
进入到这个方法org.springframework.web.util.UrlPathHelper#decodeRequestString
public String decodeRequestString(HttpServletRequest request, String source) { if (this.urlDecode && source != null) { // 标准解码 -》 return decodeInternal(request, source); } return source; }
进入到这个方法org.springframework.web.util.UrlPathHelper#decodeInternal
private String decodeInternal(HttpServletRequest request, String source) { // 从request中获取编码格式,若是没有采用ISO-8859-1编码 -》 String enc = determineEncoding(request); try { return UriUtils.decode(source, enc); } catch (UnsupportedEncodingException ex) { if (logger.isWarnEnabled()) { logger.warn("Could not decode request string [" + source + "] with encoding '" + enc + "': falling back to platform default encoding; exception message: " + ex.getMessage()); } return URLDecoder.decode(source); } }
进入到这个方法org.springframework.web.util.UrlPathHelper#determineEncoding
protected String determineEncoding(HttpServletRequest request) { String enc = request.getCharacterEncoding(); if (enc == null) { enc = getDefaultEncoding(); } return enc; }
往上返回到这个方法org.springframework.web.util.UrlPathHelper#getRequestUri
public String getRequestUri(HttpServletRequest request) { // 从request中获取请求资源路径 String uri = (String) request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE); if (uri == null) { uri = request.getRequestURI(); } return decodeAndCleanUriString(request, uri); }
往上返回到这个方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<Match>(); // 根据url查找映射 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { // 添加匹配的映射 -》 addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // No choice but to go through all mappings... addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } if (!matches.isEmpty()) { Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); Collections.sort(matches, comparator); if (logger.isTraceEnabled()) { logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches); } Match bestMatch = matches.get(0); if (matches.size() > 1) { if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}"); } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); // hander匹配 handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
进入到这个方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#addMatchingMappings
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) { for (T mapping : mappings) { // 获取匹配的映射 -》 T match = getMatchingMapping(mapping, request); if (match != null) { matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping))); } } }
进入到这个方法org.springframework.web.servlet.mvc.method.RequestMappingInfo#getMatchingCondition
@Override public RequestMappingInfo getMatchingCondition(HttpServletRequest request) { // 获取匹配的方法 -》 RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request); // 参数匹配 ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request); // headers匹配 HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request); ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request); // -》 ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request); if (methods == null || params == null || headers == null || consumes == null || produces == null) { return null; } PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request); if (patterns == null) { return null; } RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request); if (custom == null) { return null; } return new RequestMappingInfo(this.name, patterns, methods, params, headers, consumes, produces, custom.getCondition()); }
进入到这个方法org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#getMatchingCondition
@Override public RequestMethodsRequestCondition getMatchingCondition(HttpServletRequest request) { // 是否跨域 -》 if (CorsUtils.isPreFlightRequest(request)) { // 跨域匹配 -》 return matchPreFlight(request); } if (getMethods().isEmpty()) { if (RequestMethod.OPTIONS.name().equals(request.getMethod()) && !DispatcherType.ERROR.equals(request.getDispatcherType())) { return null; // No implicit match for OPTIONS (we handle it) } return this; } return matchRequestMethod(request.getMethod()); }
进入到这个方法org.springframework.web.cors.CorsUtils#isPreFlightRequest
public static boolean isPreFlightRequest(HttpServletRequest request) { return (isCorsRequest(request) && HttpMethod.OPTIONS.matches(request.getMethod()) && request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null); }
往上返回到这个方法org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#matchPreFlight
private RequestMethodsRequestCondition matchPreFlight(HttpServletRequest request) { if (getMethods().isEmpty()) { return this; } String expectedMethod = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD); // 匹配请求方法-》 return matchRequestMethod(expectedMethod); }
进入到这个方法org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#matchRequestMethod
private RequestMethodsRequestCondition matchRequestMethod(String httpMethodValue) { HttpMethod httpMethod = HttpMethod.resolve(httpMethodValue); if (httpMethod != null) { for (RequestMethod method : getMethods()) { if (httpMethod.matches(method.name())) { return new RequestMethodsRequestCondition(method); } } if (httpMethod == HttpMethod.HEAD && getMethods().contains(RequestMethod.GET)) { return GET_CONDITION; } } return null; }
往上返回到这个方法org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandlerExecutionChain
说到最后
本次源码解析仅表明我的观点,仅供参考。