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的響應處理器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM