【SpringMVC源码三千问】DispatcherServlet源码解析
DispatcherServlet#doDispatch()
是 SpringMVC 处理请求分发的方法,只要是 spring mvc 处理的 http 请求,都会经过 DispatcherServlet 的请求分发处理,从而调用相应的 handler method。
DispatcherServlet#doDispatch()
源码分析:
可以看到,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
AbstractHandlerMapping#getHandler() 中包含了对 cors 的处理,具体是往 HandlerExecutionChain 中添加了 CorsInterceptor。
@seeAbstractHandlerMapping#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() 返回的。