zoukankan      html  css  js  c++  java
  • 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()方法的调用。

  • 相关阅读:
    RecyclerView 数据刷新的几种方式 局部刷新 notify MD
    【图片】批量获取几万张图片
    RV BaseRecyclerViewAdapterHelper 总结 MD
    RecyclerView.ItemDecoration 间隔线
    Kotlin【简介】Android开发 配置 扩展
    Kotlin 特性 语法糖 优势 扩展 高阶 MD
    一个十分简洁实用的MD风格的UI主框架
    折叠伸缩工具栏 CollapsingToolbarLayout
    FloatingActionButton FAB 悬浮按钮
    Glide Picasso Fresco UIL 图片框架 缓存 MD
  • 原文地址:https://www.cnblogs.com/silenceshining/p/14045561.html
Copyright © 2011-2022 走看看