• SpringMVC中从doDispatch如何一步步调用到controller的方法


    以一个简单请求为例进行说明:

    @RestController
    public class DemoController {
    
        @GetMapping("hello")
        public String sayHello() {
            return "hello world";
        }
    }

    首先列一下doDispatch方法进行说明:

    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.根据请求的url获取处理请求的controller和controller中的方法。
                    mappedHandler = getHandler(processedRequest);
                    if (mappedHandler == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // Determine handler adapter for the current request.根据处理器的类型获取处理器的适配器,使用适配器通过反射进行真正的方法调用。
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                    // Process last-modified header, if supported by the handler.
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
    
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    // Actually invoke the handler.适配器处理请求(通过反射调用controller中的方法)。
                    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);
                    }
                }
            }
        }

    下面打断点一步步跟一下:

    1-获取mappedHandler = getHandler(processedRequest); 获取处理请求的controller信息和方法信息。

    2-HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());根据处理器获取适配器,从断点看适配器类型为:RequestMappingHandlerAdapter。

    3-mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 真正调用处理方法。

    AbstractHandlerMethodAdapter.class(RequestMappingHandlerAdapter的父类)
        @Override
      @Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            return handleInternal(request, response, (HandlerMethod) handler);
        }
    RequestMappingHandlerAdapter.class
    @Override
        protected ModelAndView handleInternal(HttpServletRequest request,
                HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
            ModelAndView mav;
          ......
    // No synchronization on session demanded at all... 调用此方法继续执行 mav = invokeHandlerMethod(request, response, handlerMethod);       ...... return mav; }
    @Nullable
        protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
          ......
            //调用此方法继续执行
                invocableMethod.invokeAndHandle(webRequest, mavContainer);
          ......
    }
    public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
                Object... providedArgs) throws Exception {
          //调用此方法继续执行
            Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
        }
    InvocableHandlerMethod.class
      @Nullable
        public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
            Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Arguments: " + Arrays.toString(args));
            }
          //调用此方法
            return this.doInvoke(args);
        }
    @Nullable
        protected Object doInvoke(Object... args) throws Exception {
            ReflectionUtils.makeAccessible(this.getBridgedMethod());
          ......
            //反射执行controller中的处理方法
    return this.getBridgedMethod().invoke(this.getBean(), args);
          ......
    }

    调试获取this.getBridgedMethod(),Method为controller中的sayHello()处理方法:

    调试获取this.getBean()为DemoCOntroller的一个对象:

    即最后通过Method.class的public Object invoke(Object obj, Object... args)方法去完成DemoController中sayHello()方法的调用。

  • 相关阅读:
    [HAOI2015] 数组游戏
    [HAOI2015] 数字串拆分
    [HAOI2015] 按位或
    [HAOI2009] 毛毛虫
    [HAOI2009] 巧克力
    [HAOI2011] Problem C
    [HAOI2011] 防线修建
    [HAOI2011] Problem A
    [HAOI2010] 最长公共子序列
    [HAOI2010] 工厂选址
  • 原文地址:https://www.cnblogs.com/silenceshining/p/14045561.html
Copyright © 2020-2023  润新知