SpringMvc源码-DispatcherServlet(二)

上一篇SpringMvc源码-DispatcherServlet讲了DispatcherServlet的初始化过程,本篇着重讲DispatchServlet处理一个请求的流程,即面试SpringMvc的经典面试题,SpringMvc是如何处理reqeuest的。

准备工作

我们的DispatchServlet继承于HttpServlet,HttpServlet处理请求的方法主要是httpServlet.service,该方法会根据request.method调用doXxx。FrameworkServlet自己去实现了doXxx。

整个的调用链是:接到reqeust请求后->FrameworkServlet.service()->FrameworkServlet.processRequest()->DispatchServlet.doService()(FrameworkServlet提供了抽象方法)
->DispatchServlet.doDispatch()处理请求

下面,我们根据这个调用链进行分析

FrameworkServlet

FrameworkServlet还重写了service方法,主要是支持HttpMethod.PATCH,它们和HttpMethod.PATCH一样都调用了processRequest(request, response)

所有的doXXX都是调用processRequest我们来看下processRequest方法做了什么

processRequest

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
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

long startTime = System.currentTimeMillis();
Throwable failureCause = null;

//从ThreadLocal中获取上一个请求的LocaleContext
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();//
//new当前请求的LocaleContext
LocaleContext localeContext = buildLocaleContext(request);//SimpleLocaleContext

//从ThreadLocal中获取上一个请求的RequestAttributes(ServletRequestAttributes)
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
//new当前请求的ServletRequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

//保存进ThreadLocal中
initContextHolders(request, localeContext, requestAttributes);

try {
//抽象方法具体实现在DeipatchServlet,重点方法
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}

finally {
//恢复previousLocaleContext,previousAttributes
//这里是我没太看明白的地方,说下我的猜测:
// 1、previousLocaleContext,previousAttributes大概率为空这里就重置了ThreadLocal
// 2、previousLocaleContext,previousAttributes不为空,说明当前线程处理别的请求,所以
// 在doservice时候context用的是current的值,请求处理完了将值还原称之前的值。
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}

doService–>doDispatch方法负责处理具体的请求逻辑

doDispatch见下面

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
ModelAndView mv = null;
Exception dispatchException = null;

try {
//判断reqeust的ContentType包含multipart/ 如果是multipart则返回StandardMultipartHttpServletRequest
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
//根据请求获取HandlerExecutionChain,包含对应的handlerMethod和interceptor【MappedInterceptor 和 HandlerIntercpetor等等】
//具体介绍见下方
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}

// Determine handler adapter for the current request.
// 根据handler找到HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}

//关键代码,执行拦截器的preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// Actually invoke the handler.
//关键代码,执行handlerMethod,ha的类型是RequestMappingHandlerAdapter,
// 调用路径是AbstractHandlerMethodAdapter.handle()-->AbstractHandlerMethodAdapter.handleInternal()-->ha的类型是RequestMappingHandlerAdapter.handleInternal
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

/**
* todo 待看的组件
* WebDataBinderFactory
* ModelFactory
*
* ServletInvocableHandlerMethod
*
* HandlerMethodArgumentResolverComposite
* HandlerMethodReturnValueHandlerComposite
*
* ModelAndViewContainer
* modelAndView
*/

//todo asyncManager 待看
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}

//todo
applyDefaultViewName(processedRequest, mv);
//关键代码,执行拦截器的postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//todo 书签 渲染modelAndView,同时触发mappedHandler.triggerAfterCompletion
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
//触发mappedHandler.triggerAfterCompletion
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
} catch (Throwable err) {
//触发mappedHandler.triggerAfterCompletion
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else {
// Clean up any resources used by a multipart request.
//这里要注意,Multipar在这里被清理掉所以如果Multipart有异步场景,需要将copy到别的对象中。
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

关键文章索引: