SpringMVC源码阅读RequestMappingHandlerAdapter如何处理Handle(八)

接口

public interface HandlerAdapter {
        /**
         * 是否能处理指定Handler
         * @param var1
         * @return
         */
        boolean supports(Object var1);

        /**
         * 处理Handler
         * @param var1
         * @param var2
         * @param var3
         * @return
         * @throws Exception
         */
        @Nullable
        ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

        /**
         * 获取资源最后一次更新时间
         * @param var1
         * @param var2
         * @return
         */
        long getLastModified(HttpServletRequest var1, Object var2);
    }

类图

 

 

 我们回到Dispatcher开始看起

DispatcherServlet

doDispatch

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#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 {
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;

                try {
                    /**
                     * 如果配置了MultipartResolver 会调用 isMultipart() 方法判断请求中是否包含文件。
                     * 如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart()
                     * 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile
                     * 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中并返回
                     */
                    processedRequest = this.checkMultipart(request);
                    //是否被解析
                    multipartRequestParsed = processedRequest != request;
                    //通过HandlerMapping获得 HandlerExecutionChanin如:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
                    //org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMappin
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        //没获取到抛出404异常
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                    //<1>返回对应能处理的HandlerAdapter
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (this.logger.isDebugEnabled()) {
                            this.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;
                    }
                    //<3>真正的处理方法 返回视图 没有视图则返回null
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    //是否开启异步管理器
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
                    //设置默认的viewName
                    this.applyDefaultViewName(processedRequest, mv);
                    //后置处理 拦截器
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var19) {
                    dispatchException = var19;
                }
                //处理正常和异常的请求调用结果。
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            } catch (Exception var20) {
                //触发异常拦截器的AfterCompletion实现
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
            } catch (Error var21) {
                //触发异常拦截器的AfterCompletion实现
                this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21);
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

<1>getHandlerAdapter

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter

 protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            Iterator var2 = this.handlerAdapters.iterator();

            while(var2.hasNext()) {
                HandlerAdapter adapter = (HandlerAdapter)var2.next();
                //<2>遍历所有适配器 传入handler 判断判断adapter是否能处理
                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

<2>supports

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports

public final boolean supports(Object handler) {
        //判断Handler是否是HandlerMethod 类型 supportsInternal是个抽象方法由子类实现 也就是RequestMappingHandlerAdapter
        return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
    }

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#supportsInternal

protected boolean supportsInternal(HandlerMethod handlerMethod) {
        return true;
    }

<3>handle

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

 public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //<4>调用子类的实现 抽象方法模板方法实现
        return this.handleInternal(request, response, (HandlerMethod)handler);
    }

<4>handleInternal

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        //<5>检查是否配置了只能处理请求 以及是否必须存在session而没有传
        this.checkRequest(request);
        ModelAndView mav;
        //是否有配置根据session加锁
        if (this.synchronizeOnSession) {
            //true为如果不存在session则创建一个并返回  false不存在直接返回null
            HttpSession session = request.getSession(false);
            if (session != null) {
                /**
                 *  Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE);
                 *  如果为空则返回当前session对象 当我们有需求保证一个session原子性的时候用吧 就一个加同步锁动作
                 */
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized(mutex) {
                    //<6>执行处理返回modelView
                    mav = this.invokeHandlerMethod(request, response, handlerMethod);
                }
            } else {
                //<6>执行处理返回modelView
                mav = this.invokeHandlerMethod(request, response, handlerMethod);
            }
        } else {
            //<6>执行处理求返回modelView
            mav = this.invokeHandlerMethod(request, response, handlerMethod);
        }

        /**
         * 响应头Cache-Control是通知浏览器缓存
         * 这里主要是@SessionAttribute用法的处理
         * 很少用到 也可兼容https://blog.csdn.net/qq_38737992/article/details/89763067 处理
         */
        if (!response.containsHeader("Cache-Control")) {
            if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
            } else {
                this.prepareResponse(response);
            }
        }

        return mav;
    }

<5>checkRequest

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

->

org.springframework.web.servlet.support.WebContentGenerator#checkRequest

protected final void checkRequest(HttpServletRequest request) throws ServletException {
        //获得请求方式
        String method = request.getMethod();
        //判断是否支持  我们可以通过这个支持的请求方式
        if (this.supportedMethods != null && !this.supportedMethods.contains(method)) {
            throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods);
            //判断是否配置了必须存在session 
        } else if (this.requireSession && request.getSession(false) == null) {
            throw new HttpSessionRequiredException("Pre-existing session required but none found");
        }
    }

<6>invokeHandlerMethod

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

 protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        ServletWebRequest webRequest = new ServletWebRequest(request, response);

        ModelAndView var15;
        try {
            WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
            ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
            //交给ServletInvocableHandlerMethod 对象代理handlerMethod
            ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
            //入参绑定器 set 后续使用
            if (this.argumentResolvers != null) {
                invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            }
            //返回值绑定器
            if (this.returnValueHandlers != null) {
                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);
            AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
            //异步超时时间
            asyncWebRequest.setTimeout(this.asyncRequestTimeout);
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
            //设置线程池
            asyncManager.setTaskExecutor(this.taskExecutor);
            asyncManager.setAsyncWebRequest(asyncWebRequest);
            //拦截器
            asyncManager.registerCallableInterceptors(this.callableInterceptors);
            //DeferredResult方式拦截器
            asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
            Object result;
            /**
             * 主要针对我们返回值是Callable 会释放Dispatcher占用的线程 交给的taskExecutor之心你那个 但是与客户端连接还保持
             * 当拿回结果 从新走Dispatcher入口进来 这里判断就会是true
             */
            if (asyncManager.hasConcurrentResult()) {
                result = asyncManager.getConcurrentResult();
                mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
                asyncManager.clearConcurrentResult();
                LogFormatUtils.traceDebug(this.logger, (traceOn) -> {
                    String formatted = LogFormatUtils.formatValue(result, !traceOn);
                    return "Resume with async result [" + formatted + "]";
                });
                //同时这类替换invocableMethod为ServletInvocableHandlerMethod.ConcurrentResultHandlerMethod 继承ServletInvocableHandlerMethod
                invocableMethod = invocableMethod.wrapConcurrentResult(result);
            }
            //<7>执行后续请求处理
            invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
            if (asyncManager.isConcurrentHandlingStarted()) {
                result = null;
                return (ModelAndView)result;
            }
            //<如果我们返回ModelAndView则会被ModelAndViewMethodReturnValueHandler 封装到 mavContainenr 这里则根据MavContainer获取
            var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
        } finally {
            webRequest.requestCompleted();
        }

        return var15;
    }

ServletInvocableHandlerMethod

<7>invokeAndHandle

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

->

org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle

  public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        //<7_1>执行参数绑定  执行控制器方法取回返回结果
        Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
        this.setResponseStatus(webRequest);
        if (returnValue == null) {
            if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
                mavContainer.setRequestHandled(true);
                return;
            }
        } else if (StringUtils.hasText(this.getResponseStatusReason())) {
            mavContainer.setRequestHandled(true);
            return;
        }

        mavContainer.setRequestHandled(false);
        //必须返回值处理器
        Assert.state(this.returnValueHandlers != null, "No return value handlers");

        try {
            //<10>通过返回值处理器进行返回值处理
            this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
        } catch (Exception var6) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace(this.formatErrorForReturnValue(returnValue), var6);
            }

            throw var6;
        }
    }

<7_1>invokeForRequest

org.springframework.web.servlet.FrameworkServlet#service

->

org.springframework.web.servlet.FrameworkServlet#processRequest

->

org.springframework.web.servlet.DispatcherServlet#doService

->

org.springframework.web.servlet.DispatcherServlet#doDispatch

->

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

->

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

->

org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle

->

org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest

 public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        //<8>通过绑定器绑定参数
        Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Arguments: " + Arrays.toString(args));
        }
        //<9>调用对应的controller方法
        return this.doInvoke(args);
    }

<8>getMethodArgumentValues

org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues

 protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        //获得对应的绑定参数
        MethodParameter[] parameters = this.getMethodParameters();
        Object[] args = new Object[parameters.length];

        for(int i = 0; i < parameters.length; ++i) {
            MethodParameter parameter = parameters[i];
            parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
            //这里是优先获取 @Init方法注册的合适的绑定器 返回的类型绑定器
            args[i] = this.resolveProvidedArgument(parameter, providedArgs);
            if (args[i] == null) {
                //遍历所有参数绑定器找到合适的绑定器
                if (this.argumentResolvers.supportsParameter(parameter)) {
                    try {
                        //解析出参数 
                        args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
                    } catch (Exception var10) {
                        if (this.logger.isDebugEnabled()) {
                            String message = var10.getMessage();
                            if (message != null && !message.contains(parameter.getExecutable().toGenericString())) {
                                this.logger.debug(formatArgumentError(parameter, message));
                            }
                        }

                        throw var10;
                    }
                } else if (args[i] == null) {
                    throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
                }
            }
        }
        //返回参数 
        return args;
    }

<9>doInvoke

org.springframework.web.method.support.InvocableHandlerMethod#doInvoke

  protected Object doInvoke(Object... args) throws Exception {
        ReflectionUtils.makeAccessible(this.getBridgedMethod());

        try {
            //反射调用对应的Method方法
            return this.getBridgedMethod().invoke(this.getBean(), args);
        } catch (IllegalArgumentException var4) {
            this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);
            String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument";
            throw new IllegalStateException(this.formatInvokeError(text, args), var4);
        } catch (InvocationTargetException var5) {
            Throwable targetException = var5.getTargetException();
            if (targetException instanceof RuntimeException) {
                throw (RuntimeException)targetException;
            } else if (targetException instanceof Error) {
                throw (Error)targetException;
            } else if (targetException instanceof Exception) {
                throw (Exception)targetException;
            } else {
                throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException);
            }
        }
    }

 <10>handleReturnValue

org.springframework.web.method.support.InvocableHandlerMethod#handleReturnValue

  public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
         //<11>根据响应值和响应参数选取合适的BindType
        HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        } else {
            //写入body 我们可以自定义绑定在写入之前执行一些逻辑
            handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
    }

<11>selectHandler

org.springframework.web.method.support.InvocableHandlerMethod#selectHandler

  @Nullable
    private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
        boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
        Iterator var4 = this.returnValueHandlers.iterator();

        HandlerMethodReturnValueHandler handler;
        do {
            do {
                if (!var4.hasNext()) {
                    return null;
                }

                handler = (HandlerMethodReturnValueHandler)var4.next();
            } while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
            //返回supportsReturnType  调用判断是否能处理
        } while(!handler.supportsReturnType(returnType));

        return handler;
    }

如:RequestBody绑定器的实现

 public boolean supportsReturnType(MethodParameter returnType) {
        return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class);
    }

总结

1.RequestMappingHandlerAdapter最终内部会将请求委托给ServletInvocableHandlerMethod处理

2.ServletInvocableHandlerMethod 会先经过参数绑定器获得参数args数组

3.然后通能反射调用Controller的对应方法

4.再通过响应绑定器对不同的响应内容做处理 比如解析@ResponseBody的响应处理器

posted @ 2020-01-21 16:57  意犹未尽  阅读(760)  评论(0编辑  收藏  举报