【SpringMVC源码三千问】DispatcherServlet源码解析

DispatcherServlet#doDispatch() 是 SpringMVC 处理请求分发的方法,只要是 spring mvc 处理的 http 请求,都会经过 DispatcherServlet 的请求分发处理,从而调用相应的 handler method。

DispatcherServlet#doDispatch() 源码分析:

DispatcherServlet.png

可以看到,DispatcherServlet#doDispatch() 的处理大体分了 6 步:
1、获取 request 对应的 HandlerExecutionChain(它包含 handler 和 interceptors)
2、获取 handler 对应的 HandlerAdapter
3、执行 handler 的前置处理: HandlerInterceptor#preHandle()
4、通过 HandlerAdapter#handler() 来执行处理程序
5、执行 handler 的后置处理:HandlerInterceptor#postHandle()
6、对返回值进行处理(包括正常返回 和 异常处理)

处理程序 handler 始终包装在 HandlerExecutionChain 实例中,HandlerExecutionChain 中可以附带一些 HandlerInterceptor
DispatcherServlet 将首先按给定顺序调用每个 HandlerInterceptor#preHandle() 方法,如果所有 preHandle 都返回 true 的话,才会调用处理程序 handler 本身。

所以,如果我们想要找 url 与 handler method 的映射关系的话,就可以从 DispatcherServlet#getHandler() 来入手,打个断点调试。

HandlerExecutionChain 的获取 和 组装

HandlerExecutionChain 是 handler 的执行链,它是由 handler 和 interceptors 组成的。

HandlerExecutionChain 是通过 DispatcherServlet#getHandler() 来获取的:

/**
 * 将所有的 HandlerMapping 按顺序遍历一次,获取 request 对应的 HandlerExecutionChain。
 */
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        for (HandlerMapping mapping : this.handlerMappings) {
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

可以看到,在获取 HandlerExecutionChain 时,Spring 会将所有的 HandlerMapping 按顺序遍历一次。
而在 Spring 中有许多 HandlerMapping,最常用的当属 RequestMappingHandlerMapping

HandlerExecutionChain 的获取

HandlerExecutionChain 的获取是在 AbstractHandlerMapping#getHandler() 中完成的。
主要分成了两步:
1、获取 request 对应的 handler 程序
2、将 handler 和 相应的 HandlerInterceptors 组装成 HandlerExecutionChain

getHandler.png

AbstractHandlerMapping#getHandler() 中包含了对 cors 的处理,具体是往 HandlerExecutionChain 中添加了 CorsInterceptor。
@see AbstractHandlerMapping#getCorsHandlerExecutionChain()

HandlerExecutionChain 的构造和组装过程

HandlerExecutionChain 的构造组装是在 AbstractHandlerMapping#getHandlerExecutionChain()

/**
 * 为给定的 handler 构建 HandlerExecutionChain(包含 handler 和 HandlerInterceptor)。
 */
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    // 1、根据 handler 构造 HandlerExecutionChain  
    HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
            (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

    // 2、给 HandlerExecutionChain 添加 HandlerInterceptor  
    for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
        if (interceptor instanceof MappedInterceptor) {
            MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
            if (mappedInterceptor.matches(request)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        } else {
            chain.addInterceptor(interceptor);
        }
    }
    return chain;
}

DispatcherServlet 中使用的默认策略接口

DispatcherServlet.properties 中指定了 DispatcherServlet.java 中使用的一些策略接口的默认实现:

# spring-webmvc-5.3.9.jar!/org/springframework/web/servlet/DispatcherServlet.properties
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
	org.springframework.web.servlet.function.support.RouterFunctionMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter


org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

小结

DispatcherServlet#doDispatch() 是 Spring MVC 处理请求分发的方法,它的处理大体分了 6 步:
1、获取 request 对应的 HandlerExecutionChain(它包含 handler 和 interceptors)
2、获取 handler 对应的 HandlerAdapter
3、执行 handler 的前置处理: HandlerInterceptor#preHandle()
4、通过 HandlerAdapter#handler() 来执行处理程序
5、执行 handler 的后置处理:HandlerInterceptor#postHandle()
6、对返回值进行处理(包括正常返回 和 异常处理)

HandlerExecutionChain 是 handler 的执行链,它是由 handler 和 interceptors 组成的。
HandlerExecutionChain 是由 HandlerMapping#getHandler() 返回的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老王学源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值