登录
    Technology changes quickly but people's minds change slowly.

spring boot web 流程分析

技术宅 破玉 1597次浏览 0个评论

spring mvc代码分析

我们都知道,spring mvc 的入口就在于 DispatcherServlet,那里面应该就有个 doDispatch 的方法
核心代码如下:

mappedHandler = this.getHandler(processedRequest);// 获取Handler
 HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());// 获取HandlerAdapter
 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// HandlerAdapter 处理,返回 ModelAndView

调用 AbstractHandlerMethodAdapter 中的如下方法:

@Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return this.handleInternal(request, response, (HandlerMethod)handler);
    }

我们看到又调用了 handleInternal ,这是个抽象方法,会根据对应的Adapter 实现来调用。这里会调用RequestMappingHandlerAdapter#handleInternal
实现如下:

protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        this.checkRequest(request);
        ModelAndView mav;
        if (this.synchronizeOnSession) {
            HttpSession session = request.getSession(false);
            if (session != null) {
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized(mutex) {
                    mav = this.invokeHandlerMethod(request, response, handlerMethod);
                }
            } else {
                mav = this.invokeHandlerMethod(request, response, handlerMethod);
            }
        } else {
            mav = this.invokeHandlerMethod(request, response, handlerMethod);
        }

        if (!response.containsHeader("Cache-Control")) {
            if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
            } else {
                this.prepareResponse(response);
            }
        }

        return mav;
    }

然后调用 invokeHandlerMethod 返回 ModelAndView,最终调用的是ServletInvocableHandlerMethod#invokeAndHandle
代码如下:

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
        this.setResponseStatus(webRequest);
        if (returnValue == null) {
            if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
                this.disableContentCachingIfNecessary(webRequest);
                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 {
            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;
        }
    }

然后执行InvocableHandlerMethod#invokeForRequest

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

        try {
            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);
            }
        }
    }

最终调用 Method 的invoke 来反射执行相关方法。当然 GET 请求和POST 请求等的处理方式是不一样的,但最终原理都是一样的。


华裳绕指柔, 版权所有丨如未注明 , 均为原创|转载请注明spring boot web 流程分析
喜欢 (1)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址