SpringMVC处理流程非常详细的讲解

环境:Spring5.3.24


1 请求入口

 public class DispatcherServlet extends FrameworkServlet {
   protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     HandlerExecutionChain mappedHandler = null;
     try {
       ModelAndView mv = null;
       Exception dispatchException = null;
       try {
         // 2.1.通过HandlerMapping获取请求处理链,该对象由处理程序(Controller,一般HandlerMethod对象)及拦截器(Interceptor)组成
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) {
           noHandlerFound(processedRequest, response);
           return;
         }
         // 2.2.根据2.1获取的处理程序(HandlerMethod)对象确定能够处理该处理程序的HandlerAdapter对象
         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
         // ...
         // 2.3.执行处理程序之前,执行拦截器preHandle方法,如果返回了false,本次请求将被终止
         if (!mappedHandler.applyPreHandle(processedRequest, response)) {
           return;
         }
 
         // 2.4.真正的执行处理程序
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
         // ...
         // 2.5.执行处理程序之后,执行拦截器postHandle方法
         mappedHandler.applyPostHandle(processedRequest, response, mv);
       } catch (Exception ex) {
         dispatchException = ex;
       } catch (Throwable err) {
         dispatchException = new NestedServletException("Handler dispatch failed", err);
       }
       // 2.6.处理结果,根据处理程序是否发生异常,是否返回有ModelAndView对象进行结果的处理
       processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
     }
     // ...
   }
 }

2 处理请求

2.1 获取请求处理链

该步骤通过HandlerMapping获取HandlerExecutionChain处理器执行链。

 public class DispatcherServlet {
   protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     if (this.handlerMappings != null) {
       // 遍历当前容器中注册的所有HandlerMapping对象
       for (HandlerMapping mapping : this.handlerMappings) {
         // 针对Controller接口,使用的是RequestMappingHandlerMapping对象
         HandlerExecutionChain handler = mapping.getHandler(request);
         if (handler != null) {
           return handler;
         }
       }
     }
     return null;
   }
 }

这里以RequestMappingHandlerMapping为例

mapping.getHandler(request)方法调用流程如下:

 public abstract class AbstractHandlerMapping {
   public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     // 调用子类实现的getHandlerInternal方法
     Object handler = getHandlerInternal(request);
     // ...
     // 根据查找到的处理程序封装到处理程序执行链
     // 这里会将拦截器也添加其中
     HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
     // ...这里是跨域相关的配置
     return executionChain;
   }
   protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
     HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
         (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
     for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
       if (interceptor instanceof MappedInterceptor) {
         MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
         if (mappedInterceptor.matches(request)) {
           chain.addInterceptor(mappedInterceptor.getInterceptor());
         }
       } else {
         chain.addInterceptor(interceptor);
       }
     }
     return chain;
   }
 }

调用子类RequestMappingInfoHandlerMapping#getHandlerInternal实现。

 public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping {
   protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
     request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
     try {
       // 又调父类的实现 ( o )…
       return super.getHandlerInternal(request);
     }
   }
 }

调用父类AbstractHandlerMethodMapping#getHandlerInternal方法

 public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMapping implements InitializingBean {
   private final MappingRegistry mappingRegistry = new MappingRegistry();
   protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
     // 根据当前的请求获取请求的uri
     String lookupPath = initLookupPath(request);
     this.mappingRegistry.acquireReadLock();
     try {
       HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
       return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
     }
   }
   protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
     List matches = new ArrayList<>();
     // 系统启动时初始化RequestMappingHandlerMapping解析了整个系统中所有的Controller然后注册到MappingRegistry中
     // 根据当前的请求uri,对应List对象,相同的uri可能对应不同的request method,所以这里返回的是List集合
     List directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
     if (directPathMatches != null) {
       // 该方法内部会根据找到的RequestMappingInfo进行遍历,根据请求信息逐个的判断对应@RequestMapping配置的属性是否匹配
       addMatchingMappings(directPathMatches, matches, request);
     }
     if (matches.isEmpty()) {
       addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
     }
     // 下面if的逻辑就是判断如果找到了匹配并且存在多个会找出最合适的
     if (!matches.isEmpty()) {
       Match bestMatch = matches.get(0);
       if (matches.size() > 1) {
         Comparator comparator = new MatchComparator(getMappingComparator(request));
         matches.sort(comparator);
         bestMatch = matches.get(0);
         if (CorsUtils.isPreFlightRequest(request)) {
           for (Match match : matches) {
             if (match.hasCorsConfig()) {
               return PREFLIGHT_AMBIGUOUS_MATCH;
             }
           }
         } else {
           Match secondBestMatch = matches.get(1);
           if (comparator.compare(bestMatch, secondBestMatch) == 0) {
             Method m1 = bestMatch.getHandlerMethod().getMethod();
             Method m2 = secondBestMatch.getHandlerMethod().getMethod();
             String uri = request.getRequestURI();
             throw new IllegalStateException(
                 "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
           }
         }
       }
       request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
       // 将当前请求uri保存到request对象中setAttribute
       handleMatch(bestMatch.mapping, lookupPath, request);
       // 返回当前uri对应的HandlerMethod对象
       return bestMatch.getHandlerMethod();
     }
   }
   protected void handleMatch(T mapping, String lookupPath, HttpServletRequest request) {
     request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath);
   }
 }

2.2 获取HandlerAdapter

在上一步中通过HandlerMapping找到了相应的HandlerMethod对象,最后封装到了HandlerExecutionChain中,接下来就是根据HandlerMethod查找合适的HandlerAdapter处理程序。

 public class DispatcherServlet {
   protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
     if (this.handlerAdapters != null) {
       // 这里的参数handler一般都是HandlerMethod对象
       for (HandlerAdapter adapter : this.handlerAdapters) {
         // 这个根据handler判断哪个HandlerAdapter支持,一般都是RequestMappingHandlerAdapter
         if (adapter.supports(handler)) {
           return adapter;
         }
       }
     }
     throw new ServletException("No adapter for handler [" + handler +
         "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
   }
 }

RequestMappingHandlerAdapter 这调用的是父类方法

 public abstract class AbstractHandlerMethodAdapter {
   public final boolean supports(Object handler) {
     return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
   }
 }
 public class RequestMappingHandlerAdapter {
   protected boolean supportsInternal(HandlerMethod handlerMethod) {
     return true;
   }
 }

2.3 执行拦截器preHandle方法

在真正调用处理程序前,执行拦截器preHandle方法

 public class HandlerExecutionChain {
   boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
     for (int i = 0; i < this.interceptorList.size(); i++) {
       HandlerInterceptor interceptor = this.interceptorList.get(i);
       // 如果任何一个拦截器返回了false,本次请求都会被终止
       if (!interceptor.preHandle(request, response, this.handler)) {
         // 该拦截器的完成回调会被执行
         triggerAfterCompletion(request, response, null);
         return false;
       }
       this.interceptorIndex = i;
     }
     return true;
   }
 }

2.4 实际请求处理

 public class DispatcherServlet {
   protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
   }
 }

AbstractHandlerMethodAdapter

 public abstract class AbstractHandlerMethodAdapter {
   public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
       throws Exception {
     // 子类重写了该方法
     return handleInternal(request, response, (HandlerMethod) handler);
   }
 }

RequestMappingHandlerAdapter

 public class RequestMappingHandlerAdapter {
   protected ModelAndView handleInternal(HttpServletRequest request, 
       HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
     ModelAndView mav;
     if (this.synchronizeOnSession) {
       // ...
     } else {
       // No synchronization on session demanded at all...
       // 执行HandlerMethod调用
       mav = invokeHandlerMethod(request, response, handlerMethod);
     }
     // ...
     return mav;
   }
   protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
       HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
 
     ServletWebRequest webRequest = new ServletWebRequest(request, response);
     try {
       // 创建数据绑定工厂,主要作用就是将请求的参数信息与Controller方法的参数进行绑定(数据类型的转换)及参数校验
       WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
       // 处理@ModelAttribute和@SessionAttribute注解,它将做两件事:
       // 1.将@SessionAttribute注解的方法的相关数据合并到下面的ModelAndViewContainer中
       // 2.将@ModelAttribute注解的方法返回值添加到ModelAndViewContainer中
       ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
       // 实际HandlerMethod调用对象
       ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
       if (this.argumentResolvers != null) {
         // 设置参数解析器
         invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
       }
       if (this.returnValueHandlers != null) {
         // 设置Controller方法返回值的处理器
         invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
       }
       invocableMethod.setDataBinderFactory(binderFactory);
       invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
 
       ModelAndViewContainer mavContainer = new ModelAndViewContainer();
       mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
       // 执行上面说的两个步骤
       modelFactory.initModel(webRequest, mavContainer, invocableMethod);
       mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
       // ...
       // 执行调用HandlerMethod
       // 在这个过程中会应用到参数解析器和返回值处理器,这里就不展开说了
       invocableMethod.invokeAndHandle(webRequest, mavContainer);
       if (asyncManager.isConcurrentHandlingStarted()) {
         return null;
       }
       // 这里会返回ModelAndView对象,这个根据情况,如果你是RestController,那么在通过返回值处理器就已经将结果进行了输出如使用@ResponseBody注解的方法
       // 如果是RestController,请求结果就提前输出了,同时会将ModelAndViewContainer的requestHandled属性设置为true。
       return getModelAndView(mavContainer, modelFactory, webRequest);
     } finally {
       webRequest.requestCompleted();
     }
   }
   private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
       ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
 
     modelFactory.updateModel(webRequest, mavContainer);
     // 如果是@ResponseBody注解的方法,那么直接返回null
     if (mavContainer.isRequestHandled()) {
       return null;
     }
     ModelMap model = mavContainer.getModel();
     ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
     if (!mavContainer.isViewReference()) {
       mav.setView((View) mavContainer.getView());
     }
     // ...
     return mav;
   }
 }

2.5 执行拦截器postHandle方法

 public class HandlerExecutionChain {
   void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
       throws Exception {
     for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
       HandlerInterceptor interceptor = this.interceptorList.get(i);
       interceptor.postHandle(request, response, this.handler, mv);
     }
   }
 }

2.6 处理结果

 public class DispatcherServlet {
   protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
   private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
       @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
       @Nullable Exception exception) throws Exception {
 
     boolean errorView = false;
 
     // 在处理过程中如果出现了异常会进入这里进行异常处理
     if (exception != null) {
       if (exception instanceof ModelAndViewDefiningException) {
         logger.debug("ModelAndViewDefiningException encountered", exception);
         mv = ((ModelAndViewDefiningException) exception).getModelAndView();
       }
       else {
         Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
         mv = processHandlerException(request, response, handler, exception);
         errorView = (mv != null);
       }
     }
 
     // 如果Controller方法返回有ModelAndView
     if (mv != null && !mv.wasCleared()) {
       // 进行视图的渲染输出到客户端
       render(mv, request, response);
       if (errorView) {
         WebUtils.clearErrorRequestAttributes(request);
       }
     }
 
     if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
       // Concurrent handling started during a forward
       return;
     }
 
     // 如果是RestController接口,那么上面的代码都不会执行
     if (mappedHandler != null) {
       // 执行拦截器的afterCompletion回调方法
       mappedHandler.triggerAfterCompletion(request, response, null);
     }
   }
 }

完毕!!!

关注
SpringMVC非常实用的过滤器
SpringMVC参数统一验证方法
SpringMVC跨域CORS的各种解决方式
SpringMVC内嵌Tomcat零配置
完全自定义实现SpringMVC核心组件
完全自定义实现SpringMVC核心组件

展开阅读全文

页面更新:2024-03-12

标签:子类   遍历   组件   异常   接口   流程   对象   核心   参数   程序   方法   详细

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top