springMVC源码分析

Controller方法执行的本质

在这里插入图片描述

在这里插入图片描述

由以上两张图可以看出,controller方法执行的本质是spring将controller类的Method抽出来,在执行的时候使用java的反射进行方法的调用,此处具体为InvocableHandlerMethod进行调用

在这里插入图片描述

我们跟随debugger继续,可以看到,是InvocableHandlerMethod的子类实例ServletInvocableHandlerMethod触发的方法调用

ServletInvocableHandlerMethod的实现关系如图

在这里插入图片描述

HandlerMethod是spring对于controller控制器的方法进行的封装,内容大致如下

在这里插入图片描述

那么springMVC是如何明确具体是用哪个HandlerMethod执行的呢?根据debugger栈信息方法名,我们先大致明确spring的执行逻辑

在这里插入图片描述

根据栈信息可以看出,spring并不是直接找到HandlerMethod进行方法调用,而是中间调用了RequestMappingHandlerAdapter,按照字面意思翻译就是请求映射处理器的适配器,这里使用了适配器的模式,因为HandlerMethod简单来说就只是一个方法,执行之后就一个返回值,而在springMVC中,我们处理完返回之后可能还会涉及到参数转换,参数验证视图处理,返回结果处理的等逻辑,所以spring此处用适配器来封装相关逻辑。

在这里插入图片描述

在这里插入图片描述

上图可以看出,处理器的映射有多种方式,此处我们使用的requestMapping

在这里插入图片描述

在这里插入图片描述

此处通过各种map,list查出url,请求方法映射出的来的HandlerMethod

在这里插入图片描述

springMVC执行流程

  1. 用户发起Http请求,由tomcat进行http协议的解析,封装为request对象传递给Filter链执行

  2. Filter执链执行完,传递request对象到DispatcherServlet(实现servlet接口,具有servlet的功能)

  3. DispatcherServlet根据request获取映射到的HandlerExecutionChain,这是一个处理器执行链,部分代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class HandlerExecutionChain {

    private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
    //处理器对象
    private final Object handler;
    //拦截器数组
    @Nullable
    private HandlerInterceptor[] interceptors;

    @Nullable
    private List<HandlerInterceptor> interceptorList;
DispatcherServlet有个handlerMappings属性,是一个保存所有处理器映射的列表,我们常用的便是其中的一个实现类RequestMappingHandlerMapping,RequestMappingHandlerMapping的抽象父类AbstractHandlerMapping重写了handlerMappings的getHandler方法,使用了模板设计模式,真正获取handler对象的方法交由子类实现,部分代码如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//交由子类实现
Object handler = getHandlerInternal(request);
//未获取到handler,尝试获取默认handler
if (handler == null) {
handler = getDefaultHandler();
}
//都不存在,返回null
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//根据handler获取到完整的处理器链,包含拦截器
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//跨域请求处理
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
  1. 获取到处理器链对象之后,还需要找到对应的适配器,DispatcherServlet中的handlerAdapters属性是一个保存适配器的列表,springmvc会遍历这个列表,查出支持当前处理器链对象的适配器,有以下几种适配器实现:

    • RequestMappingHandlerAdapter : 支持handler为HandlerMethod的实现类的处理器
    • HttpRequestHandlerAdapter : 支持handler是HttpRequestHandler的实现类处理器
    • SimpleControllerHandlerAdapter : 支持handler是controller接口映射的处理器

      此处查出来的handler是HandlerMethod,所以对应的适配器为RequestMappingHandlerAdapter

  2. HandlerAdapter执行handler方法,代码如下:

通过调用RequestMappingHandlerAdapter实现的handleInternal方法执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
	ModelAndView mav;
checkRequest(request);

// Execute invokeHandlerMethod in synchronized block if required.
//如果要求在session中线程安全执行,则会加入使用synchronized加锁保证线程安全
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}

if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}

return mav;
invokeHandlerMethod方法,根据HandlerMethod会创建一个ServletInvocableHandlerMethod,通过调用其invokeAndHandle方法,执行controller对应method的逻辑并处理模型视图容器(mavContainer),再通过mavContainer返回模型视图对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
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);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}

invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}

return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}