springmvc源码解析之DispatcherServlet一

说在前面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

 

说到最后

本次源码解析仅表明我的观点,仅供参考。

相关文章
相关标签/搜索