SpringMVC的执行流程及初始化流程

鼠扑  金牌会员 | 2024-4-21 22:42:39 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 939|帖子 939|积分 2817

今天大致来看一下Spring MVC的执行流程和初始化流程是什么样的
1,执行流程:也就是一个请求是怎么到我们Controller的
2,初始化流程:也就是那些 HandlerMapping、HandlerAdapter是怎么初始化并让我们拿到的
执行流程

我们都知道 DispatcherServlet(前端控制器) 这样的一个类,是这个类来帮我们执行的,网上的很多图以这个类为核心来画的,那是怎么来到这个类的?(大多数文章并没有说)又是怎么帮我们调用各个组件来执行这个请求的?这些都是问题,我们直接来看源码,看完源码再来画图理解。
首先创建一个最简单的项目:直接使用 Spring Initializer 来帮我们快速创建出一个Web项目,地址使用阿里的(https://start.aliyun.com),依赖就选择一个 starter-web 就行,就最简单的项目。
先来到我们创建的这个项目的这个类的 BasicController#hello() 方法,并在这个上面打一个断点,然后启动项目 向这个地址发送一个请求:

还记得我们上篇文章说的怎么看源码的事情吗?直接来看调用栈:

我们通过调用栈又可以发现:

  • 红色框里是我们自己的代码
  • 紫色框里就是执行流程相关的了,SpringMVC 的底层不就是Servlet 吗。Servlet 不就是我们 JavaWeb 学的东西吗?Servlet、Filter、Listener 三大组件。
  • 蓝色框里是一些 filter 过滤器
我们直接在这里打一个断点,开始的地方:
HttpServlet

javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)

先到 javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse) ,
然后 org.springframework.web.servlet.FrameworkServlet#service,
再到 javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
javax.servlet.http.HttpServletResponse),我们来看一下这个方法:
  1.     protected void service(HttpServletRequest req, HttpServletResponse resp)
  2.         throws ServletException, IOException {
  3.         String method = req.getMethod();
  4.         if (method.equals(METHOD_GET)) {
  5.             long lastModified = getLastModified(req);
  6.             if (lastModified == -1) {
  7.                 // servlet doesn't support if-modified-since, no reason
  8.                 // to go through further expensive logic
  9.                 doGet(req, resp);
  10.             } else {
  11.                 long ifModifiedSince;
  12.                 try {
  13.                     ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
  14.                 } catch (IllegalArgumentException iae) {
  15.                     // Invalid date header - proceed as if none was set
  16.                     ifModifiedSince = -1;
  17.                 }
  18.                 if (ifModifiedSince < (lastModified / 1000 * 1000)) {
  19.                     // If the servlet mod time is later, call doGet()
  20.                     // Round down to the nearest second for a proper compare
  21.                     // A ifModifiedSince of -1 will always be less
  22.                     maybeSetLastModified(resp, lastModified);
  23.                     doGet(req, resp);
  24.                 } else {
  25.                     resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
  26.                 }
  27.             }
  28.         } else if (method.equals(METHOD_HEAD)) {
  29.             long lastModified = getLastModified(req);
  30.             maybeSetLastModified(resp, lastModified);
  31.             doHead(req, resp);
  32.         } else if (method.equals(METHOD_POST)) {
  33.             doPost(req, resp);
  34.         } else if (method.equals(METHOD_PUT)) {
  35.             doPut(req, resp);
  36.         } else if (method.equals(METHOD_DELETE)) {
  37.             doDelete(req, resp);
  38.         } else if (method.equals(METHOD_OPTIONS)) {
  39.             doOptions(req,resp);
  40.         } else if (method.equals(METHOD_TRACE)) {
  41.             doTrace(req,resp);
  42.         } else {
  43.             //
  44.             // Note that this means NO servlet supports whatever
  45.             // method was requested, anywhere on this server.
  46.             //
  47.             String errMsg = lStrings.getString("http.method_not_implemented");
  48.             Object[] errArgs = new Object[1];
  49.             errArgs[0] = method;
  50.             errMsg = MessageFormat.format(errMsg, errArgs);
  51.             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
  52.         }
  53.     }
复制代码
分析:就是根据不同的请求方式去执行。doGet、doPost、doPut、doDelete、doHead、doTrace。我们总共支持这么多种的请求方式

FrameworkServlet

我们这次的请求方式是 Get ,所以就来到了 org.springframework.web.servlet.FrameworkServlet#doGet 方法:
  1.         @Override
  2.         protected final void doGet(HttpServletRequest request, HttpServletResponse response)
  3.                         throws ServletException, IOException {
  4.                 processRequest(request, response);
  5.         }
复制代码
这里面又调用了 org.springframework.web.servlet.FrameworkServlet#processRequest 方法:
  1.         protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
  2.                         throws ServletException, IOException {
  3.                 long startTime = System.currentTimeMillis();
  4.                 Throwable failureCause = null;
  5.                 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
  6.                 LocaleContext localeContext = buildLocaleContext(request);
  7.                 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
  8.                 ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
  9.                 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  10.                 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
  11.                 initContextHolders(request, localeContext, requestAttributes);
  12.                 try {
  13.             // 继续调用执行
  14.                         doService(request, response);
  15.                 }
  16.                 catch (ServletException | IOException ex) {
  17.                         failureCause = ex;
  18.                         throw ex;
  19.                 }
  20.                 catch (Throwable ex) {
  21.                         failureCause = ex;
  22.                         throw new NestedServletException("Request processing failed", ex);
  23.                 }
  24.                 finally {
  25.                         resetContextHolders(request, previousLocaleContext, previousAttributes);
  26.                         if (requestAttributes != null) {
  27.                                 requestAttributes.requestCompleted();
  28.                         }
  29.                         logResult(request, response, failureCause, asyncManager);
  30.                         publishRequestHandledEvent(request, response, startTime, failureCause);
  31.                 }
  32.         }
复制代码
DispatcherServlet

这里面调用了 doService() 方法,这里的 doService() 方法是 **DispatcherServlet **类的:
  1.         protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2.                 logRequest(request);
  3.                 // Keep a snapshot of the request attributes in case of an include,
  4.                 // to be able to restore the original attributes after the include.
  5.                 Map<String, Object> attributesSnapshot = null;
  6.                 if (WebUtils.isIncludeRequest(request)) {
  7.                         attributesSnapshot = new HashMap<>();
  8.                         Enumeration<?> attrNames = request.getAttributeNames();
  9.                         while (attrNames.hasMoreElements()) {
  10.                                 String attrName = (String) attrNames.nextElement();
  11.                                 if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
  12.                                         attributesSnapshot.put(attrName, request.getAttribute(attrName));
  13.                                 }
  14.                         }
  15.                 }
  16.                 // Make framework objects available to handlers and view objects.
  17.                 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
  18.                 request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
  19.                 request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
  20.                 request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
  21.                 if (this.flashMapManager != null) {
  22.                         FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
  23.                         if (inputFlashMap != null) {
  24.                                 request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
  25.                         }
  26.                         request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
  27.                         request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
  28.                 }
  29.                 try {
  30.             // 核心方法
  31.                         doDispatch(request, response);
  32.                 }
  33.                 finally {
  34.                         if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  35.                                 // Restore the original attribute snapshot, in case of an include.
  36.                                 if (attributesSnapshot != null) {
  37.                                         restoreAttributesAfterInclude(request, attributesSnapshot);
  38.                                 }
  39.                         }
  40.                 }
  41.         }
复制代码
经过一层层的调用后,终于来到了最核心的方法 doDispatch()
  1.     // 文件上传解析器
  2.     /** MultipartResolver used by this servlet. */
  3.         @Nullable
  4.         private MultipartResolver multipartResolver;
  5.     // 处理器映射器集合
  6.     /** List of HandlerMappings used by this servlet. */
  7.         @Nullable
  8.         private List<HandlerMapping> handlerMappings;
  9.     // 处理器适配器集合
  10.         /** List of HandlerAdapters used by this servlet. */
  11.         @Nullable
  12.         private List<HandlerAdapter> handlerAdapters;
  13.     // 视图解析器集合
  14.         /** List of ViewResolvers used by this servlet. */
  15.         @Nullable
  16.         private List<ViewResolver> viewResolvers;
  17.         protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  18.                 HttpServletRequest processedRequest = request;
  19.         // 处理器执行器链
  20.                 HandlerExecutionChain mappedHandler = null;
  21.                 boolean multipartRequestParsed = false;
  22.                 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  23.                 try {
  24.                         ModelAndView mv = null;
  25.                         Exception dispatchException = null;
  26.                         try {
  27.                 // 是否是文件上传的请求,如果是需要包装一下
  28.                                 processedRequest = checkMultipart(request);
  29.                                 multipartRequestParsed = (processedRequest != request);
  30.                                 // 通过当前请求拿到对应的 HandlerExecutionChain 对象
  31.                 // 这一步是 HandlerMapping
  32.                                 mappedHandler = getHandler(processedRequest);
  33.                                 if (mappedHandler == null) {
  34.                                         noHandlerFound(processedRequest, response);
  35.                                         return;
  36.                                 }
  37.                                 // 通过 HandlerExecutionChain 对象里的 Handler 拿到 HandlerAdapter 对象
  38.                 // 这一步是 HandlerAdapter
  39.                                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  40.                                 // Process last-modified header, if supported by the handler.
  41.                                 String method = request.getMethod();
  42.                                 boolean isGet = "GET".equals(method);
  43.                                 if (isGet || "HEAD".equals(method)) {
  44.                                         long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
  45.                                         if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
  46.                                                 return;
  47.                                         }
  48.                                 }
  49.                 // 拦截器的前置处理
  50.                                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
  51.                                         return;
  52.                                 }
  53.                                 // 通过 HandlerAdapter 来执行我们 Controller 里的方法
  54.                                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  55.                                 if (asyncManager.isConcurrentHandlingStarted()) {
  56.                                         return;
  57.                                 }
  58.                                 applyDefaultViewName(processedRequest, mv);
  59.                 // 拦截器的后置处理
  60.                                 mappedHandler.applyPostHandle(processedRequest, response, mv);
  61.                         }
  62.                         catch (Exception ex) {
  63.                                 dispatchException = ex;
  64.                         }
  65.                         catch (Throwable err) {
  66.                                 // As of 4.3, we're processing Errors thrown from handler methods as well,
  67.                                 // making them available for @ExceptionHandler methods and other scenarios.
  68.                                 dispatchException = new NestedServletException("Handler dispatch failed", err);
  69.                         }
  70.             // 拦截器的最终处理 还会渲染 ModelAndView 对象
  71.                         processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  72.                 }
  73.                 catch (Exception ex) {
  74.                         triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
  75.                 }
  76.                 catch (Throwable err) {
  77.                         triggerAfterCompletion(processedRequest, response, mappedHandler,
  78.                                         new NestedServletException("Handler processing failed", err));
  79.                 }
  80.                 finally {
  81.                         if (asyncManager.isConcurrentHandlingStarted()) {
  82.                                 // Instead of postHandle and afterCompletion
  83.                                 if (mappedHandler != null) {
  84.                                         mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
  85.                                 }
  86.                         }
  87.                         else {
  88.                                 // Clean up any resources used by a multipart request.
  89.                                 if (multipartRequestParsed) {
  90.                                         cleanupMultipart(processedRequest);
  91.                                 }
  92.                         }
  93.                 }
  94.         }
复制代码
分析:我们这里把几个核心的方法拿过来,然后一一做拆解
1,getHandler(): 在这里 HandlerMapping 会根据当前请求拿到 HandlerExecutionChain 对象
2,getHandlerAdapter():会拿到支持处理此 HandlerHandlerAdapter 对象
3,mappedHandler.applyPreHandle():拦截器的前置处理
4,ha.handle(): 通过 HandlerAdapter 来处理
5,mappedHandler.applyPostHandle(): 拦截器的后置处理
6,processDispatchResult(): 处理结果、拦截器的最终处理
7,上面的那几个属性在启动的时候会初始化好,在初始化的时候再说
getHandler()
  1.     private List<HandlerMapping> handlerMappings;
  2.         protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  3.                 if (this.handlerMappings != null) {
  4.                         for (HandlerMapping mapping : this.handlerMappings) {
  5.                                 HandlerExecutionChain handler = mapping.getHandler(request);
  6.                                 if (handler != null) {
  7.                                         return handler;
  8.                                 }
  9.                         }
  10.                 }
  11.                 return null;
  12.         }
复制代码
分析:就是拿到所有的 HandlerMapping 调用它的 getHandler() 方法来拿到一个 HandlerExecutionChain 对象
就是这个五个 HandlerMapping 对象,可自己查询这几个各自的作用

HandlerMapping

就是根据路径找到对应的 HandlerMethod(Handler)、HandlerInterceptor、然后处理跨域,并封装为 HandlerExecutionChain 对象返回。
第一次拿到的是 RequestMappingHandlerMapping,来到 AbstractHandlerMapping#getHandler() 方法:AbstractHandlerMapping 是它的父类:
正好这个 **HandlerMapping **就能找到我们的 Handler。
  1.     private Object defaultHandler;
  2.         public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  3.         // 根据当前请求拿到对应的 Handler
  4.                 Object handler = getHandlerInternal(request);
  5.         // 没拿到就给一个默认的 Handler
  6.                 if (handler == null) {
  7.                         handler = getDefaultHandler();
  8.                 }
  9.                 if (handler == null) {
  10.                         return null;
  11.                 }
  12.                 // Bean name or resolved handler?
  13.                 if (handler instanceof String) {
  14.                         String handlerName = (String) handler;
  15.                         handler = obtainApplicationContext().getBean(handlerName);
  16.                 }
  17.         // 根据拿到的 Handler 和 当前请求得到一个 HandlerExecutionChain
  18.                 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
  19.                 if (logger.isTraceEnabled()) {
  20.                         logger.trace("Mapped to " + handler);
  21.                 }
  22.                 else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
  23.                         logger.debug("Mapped to " + executionChain.getHandler());
  24.                 }
  25.         // 跨域处理
  26.                 if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
  27.                         CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
  28.                         CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
  29.                         config = (config != null ? config.combine(handlerConfig) : handlerConfig);
  30.                         executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
  31.                 }
  32.                 return executionChain;
  33.         }
复制代码
getHandlerInternal()

来到 org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getHandlerInternal
  1.         protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
  2.                 request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
  3.                 try {
  4.             // 调用父类的方法来处理
  5.                         return super.getHandlerInternal(request);
  6.                 }
  7.                 finally {
  8.                         ProducesRequestCondition.clearMediaTypesAttribute(request);
  9.                 }
  10.         }
复制代码
它的父类是 AbstractHandlerMethodMapping ,所以又来到它这里来处理:
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal
  1.     private UrlPathHelper urlPathHelper = new UrlPathHelper();
  2.         protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
  3.         // 拿到请求中的请求路径
  4.                 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
  5.                 request.setAttribute(LOOKUP_PATH, lookupPath);
  6.                 this.mappingRegistry.acquireReadLock();
  7.                 try {
  8.             // 通过请求路径拿到 HandlerMethod (核心)
  9.                         HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
  10.                         return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
  11.                 }
  12.                 finally {
  13.                         this.mappingRegistry.releaseReadLock();
  14.                 }
  15.         }
复制代码

lookupHandlerMethod()

我们直接来看一下是怎么拿到 HandlerMethod 的:
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod
  1.         protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
  2.         // 根据路径匹配到的集合
  3.                 List<Match> matches = new ArrayList<>();
  4.         
  5.         // 1,根据路径找到对应的 RequestMappingInfo 集合
  6.                 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
  7.                 if (directPathMatches != null) {
  8.             // 2,匹配到的集合  这里面有 HandlerMethod 对象
  9.                         addMatchingMappings(directPathMatches, matches, request);
  10.                 }
  11.                 if (matches.isEmpty()) {
  12.                         // No choice but to go through all mappings...
  13.                         addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
  14.                 }
  15.                 if (!matches.isEmpty()) {
  16.             // 3,从匹配到的集合中拿到第一个
  17.                         Match bestMatch = matches.get(0);
  18.                         if (matches.size() > 1) {
  19.                                 Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
  20.                                 matches.sort(comparator);
  21.                                 bestMatch = matches.get(0);
  22.                                 if (logger.isTraceEnabled()) {
  23.                                         logger.trace(matches.size() + " matching mappings: " + matches);
  24.                                 }
  25.                                 if (CorsUtils.isPreFlightRequest(request)) {
  26.                                         return PREFLIGHT_AMBIGUOUS_MATCH;
  27.                                 }
  28.                                 Match secondBestMatch = matches.get(1);
  29.                                 if (comparator.compare(bestMatch, secondBestMatch) == 0) {
  30.                                         Method m1 = bestMatch.handlerMethod.getMethod();
  31.                                         Method m2 = secondBestMatch.handlerMethod.getMethod();
  32.                                         String uri = request.getRequestURI();
  33.                                         throw new IllegalStateException(
  34.                                                         "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
  35.                                 }
  36.                         }
  37.                         request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
  38.             // 3
  39.                         handleMatch(bestMatch.mapping, lookupPath, request);
  40.                         return bestMatch.handlerMethod;
  41.                 }
  42.                 else {
  43.                         return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
  44.                 }
  45.         }
复制代码
总结:
1,先根据路径找到对应的 RequestMappingInfo
2,再根据找到的 RequestMappingInfo 来找 HandlerMethod 然后封装为 Match 对象,添加到 matches 集合中
3,拿到 matches 集合中的第一个元素,然后通过 handleMatch() 方法来处理
1,先调用了这个方法来找到对应的 RequestMappingInfo 集合:
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#getMappingsByUrl

注意:

  • PathVariable类型是不会加到这个集合里的,具体逻辑在这里,有兴趣可以去看这两个方法:
    org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register()、org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#getDirectUrls()
  • 这里的集合 key 是路径,value 是 RequestMappingInfo
2,得到结果后返回到 lookupHandlerMethod(),继续调用 addMatchingMappings() 方法,来找匹配到的 HandlerMethod:
  1.         private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
  2.                 for (T mapping : mappings) {
  3.             // 封装一下
  4.                         T match = getMatchingMapping(mapping, request);
  5.                         if (match != null) {
  6.                 // 找到的集合,又会封装为 Match 对象
  7.                                 matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
  8.                         }
  9.                 }
  10.         }
复制代码
这里的是:key是 RequestMappingInfo,value是 HandlerMethod

这就是我们找到的 Match 集合:

我们这里就找到了,然后返回到 lookupHandlerMethod() 方法来继续,会先拿到集合中的第一个元素,然后调用 handleMatch() 来处理路径问
题,最后返回Match 对象中的 HandlerMethod。到这一步,我们终于拿到了想到的 HandlerMethod对象!
HandlerMethod



这个对象里面封装了我们的:对应的类、对应的方法、方法的参数类型、方法的返回值类型等等一系列信息
getHandlerExecutionChain()

然后一路返回到 getHandlerInternal() 方法,并调用其中的 getHandlerExecutionChain() 方法来得到 HandlerExecutionChain 对象:
  1.         protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
  2.                 HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
  3.                                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
  4.         // 拿到路径
  5.                 String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
  6.                 for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
  7.                         if (interceptor instanceof MappedInterceptor) {
  8.                                 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
  9.                                 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
  10.                                         chain.addInterceptor(mappedInterceptor.getInterceptor());
  11.                                 }
  12.                         }
  13.                         else {
  14.                                 chain.addInterceptor(interceptor);
  15.                         }
  16.                 }
  17.                 return chain;
  18.         }
复制代码
分析:
1,先把 HandlerMethod 封装到 HandlerExecutionChain 中
2,拿到路径,再遍历所有的拦截器并添加到我们的 HandlerExecutionChain 对象中,然后返回
HandlerExecutionChain

里面就仨东西:处理器、拦截器集合、当前执行到第几个拦截器的索引
跨域处理

暂无。后续补充
经过这一波操作,我们终于拿到了对应的 HandlerExecutionChain 对象。
getHandlerAdapter()

终于到了我们 HandlerAdapter 了
拿到对应的 HandlerExecutionChain 对象后,我们就该调用 getHandlerAdapter() 方法来拿能处理我们 Handler 的 HandlerAdapter:
  1.         protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
  2.                 if (this.handlerAdapters != null) {
  3.                         for (HandlerAdapter adapter : this.handlerAdapters) {
  4.                                 if (adapter.supports(handler)) {
  5.                                         return adapter;
  6.                                 }
  7.                         }
  8.                 }
  9.                 throw new ServletException("No adapter for handler [" + handler +
  10.                                 "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
  11.         }
复制代码
分析:还是遍历 HandlerAdapter 集合,来调用每一个的 supports() 方法来判断当前是否支持处理这个 Handler。

其实即使判断当前的这个 Handler 是不是某一个类。我们直接来看看
各个类的 supports() 方法:
  1.     //*****************AbstractHandlerMethodAdapter 和 RequestMappingHandlerAdapter********************************
  2.         public final boolean supports(Object handler) {
  3.                 return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
  4.         }
  5.         protected boolean supportsInternal(HandlerMethod handlerMethod) {
  6.                 return true;
  7.         }
  8.     // *******************HandlerFunctionAdapter*********************************************
  9.         public boolean supports(Object handler) {
  10.                 return handler instanceof HandlerFunction;
  11.         }
  12.     // *******************HttpRequestHandlerAdapter*********************************************
  13.         public boolean supports(Object handler) {
  14.                 return (handler instanceof HttpRequestHandler);
  15.         }
  16.     //*******************SimpleControllerHandlerAdapter*********************************************
  17.           public boolean supports(Object handler) {
  18.                 return (handler instanceof Controller);
  19.         }
复制代码
我们这里 RequestMappingHandlerAdapter 就能处理,因为我们之前拿到的就是一个 HandlerMethod。
还有一种继承 AbstractController 类来实现的,就是通过 SimpleControllerHandlerAdapter 来处理的,因为 AbstractController 是 Controller 的子类
到此我们就拿到了对应的 HandlerAdapter,这一步还是比较简单的。
mappedHandler.applyPreHandle()

拦截器的前置处理:
  1.         boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2.                 HandlerInterceptor[] interceptors = getInterceptors();
  3.                 if (!ObjectUtils.isEmpty(interceptors)) {
  4.                         for (int i = 0; i < interceptors.length; i++) {
  5.                                 HandlerInterceptor interceptor = interceptors[i];
  6.                                 if (!interceptor.preHandle(request, response, this.handler)) {
  7.                                         triggerAfterCompletion(request, response, null);
  8.                                         return false;
  9.                                 }
  10.                                 this.interceptorIndex = i;
  11.                         }
  12.                 }
  13.                 return true;
  14.         }
复制代码
分析:就是拿到我们 HandlerExecutionChain 对象里的 HandlerInterceptor 然后遍历调用其前置处理的方法,每处理成功一个就把当前索引赋值给 interceptorIndex 。以便后面拦截器的倒序处理
ha.handle()

这个其实就是用反射来调用我们的方法。invoke()
mappedHandler.applyPostHandle()

拦截器的后置处理
  1.         void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
  2.                         throws Exception {
  3.                 HandlerInterceptor[] interceptors = getInterceptors();
  4.                 if (!ObjectUtils.isEmpty(interceptors)) {
  5.                         for (int i = interceptors.length - 1; i >= 0; i--) {
  6.                                 HandlerInterceptor interceptor = interceptors[i];
  7.                 // 后置处理
  8.                                 interceptor.postHandle(request, response, this.handler, mv);
  9.                         }
  10.                 }
  11.         }
复制代码
这一次就是倒序处理了。
processDispatchResult()

拦截器的最终处理、还会处理结果 ModelAndView
  1.         private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
  2.                         @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
  3.                         @Nullable Exception exception) throws Exception {
  4.                 boolean errorView = false;
  5.                 if (exception != null) {
  6.                         if (exception instanceof ModelAndViewDefiningException) {
  7.                                 logger.debug("ModelAndViewDefiningException encountered", exception);
  8.                                 mv = ((ModelAndViewDefiningException) exception).getModelAndView();
  9.                         }
  10.                         else {
  11.                                 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
  12.                                 mv = processHandlerException(request, response, handler, exception);
  13.                                 errorView = (mv != null);
  14.                         }
  15.                 }
  16.                 // Did the handler return a view to render?
  17.                 if (mv != null && !mv.wasCleared()) {
  18.             // 视图解析器渲染结果
  19.                         render(mv, request, response);
  20.                         if (errorView) {
  21.                                 WebUtils.clearErrorRequestAttributes(request);
  22.                         }
  23.                 }
  24.                 else {
  25.                         if (logger.isTraceEnabled()) {
  26.                                 logger.trace("No view rendering, null ModelAndView returned.");
  27.                         }
  28.                 }
  29.                 if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  30.                         // Concurrent handling started during a forward
  31.                         return;
  32.                 }
  33.                 if (mappedHandler != null) {
  34.                         // 拦截器的最终处理
  35.                         mappedHandler.triggerAfterCompletion(request, response, null);
  36.                 }
  37.         }
复制代码
由于我们这个是json格式,所以没有 ModelAndView,所以来到拦截器的最终处理:
  1.         void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
  2.                         throws Exception {
  3.                 HandlerInterceptor[] interceptors = getInterceptors();
  4.                 if (!ObjectUtils.isEmpty(interceptors)) {
  5.                         for (int i = this.interceptorIndex; i >= 0; i--) {
  6.                                 HandlerInterceptor interceptor = interceptors[i];
  7.                                 try {
  8.                                         interceptor.afterCompletion(request, response, this.handler, ex);
  9.                                 }
  10.                                 catch (Throwable ex2) {
  11.                                         logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
  12.                                 }
  13.                         }
  14.                 }
  15.         }
复制代码
这次 i = interceptorIndex,第一次前置处理的时候给这个属性赋的值
到这里 doDispatch() 方法就执行完毕了。
初始化

暂无。
后记


  • 跨域的处理
  • 返回是 json 格式的时候是怎么处理的?
  • 流程图待画
  • 初始化的流程
有机会再填坑吧。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

鼠扑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表