SpringMVC 源码之网络请求(1)

FrameworkServlet#service

定位: org.springframework.web.servlet.FrameworkServlet#service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获得请求方法
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
// 处理patch请求
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
}
else {
// 处理其他类型的请求
super.service(request, response);
// 此父类方法调用了 javax.servlet.http.HttpServlet#doGet/doPost 等方法
// 同时子类 FrameworkServlet 重写了 doGet/doPost, 继续调用了 FrameworkServlet#processRequest
// 即此方法最终都会调用 FrameworkServlet#processRequest
}
}

FrameworkServlet#processRequest

定位: org.springframework.web.servlet.FrameworkServlet#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
50
51
52
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

// 记录当前时间,用于计算处理请求花费的时间
long startTime = System.currentTimeMillis();
// 记录异常,用于保存处理请求过程中发送的异常
Throwable failureCause = null;

// 获取LocaleContextHolder中原来保存的LocaleContext(保存的本地化信息)
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
// 获取当前请求的LocaleContext
LocaleContext localeContext = buildLocaleContext(request);

// 获取RequestContextHolder总原来保存的RequestAttribute(管理request和session的属性)
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 获取当前请求的ServletRequestAttribute
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

// 获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

// 将当前请求的LocaleContext和ServletRequestAttribute设置到LocaleContextHolder和RequestContextHolder
initContextHolders(request, localeContext, requestAttributes);

try {
// 执行真正的逻辑
doService(request, response);
}
catch (ServletException | IOException ex) {
// 记录抛出的异常
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
// 记录抛出的异常
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}

finally {
// 恢复原来的LocaleContext和ServletRequestAttributes到LocaleContextHolder和RequestContextHolder中
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
// 如果日志级别为debug,则打印请求日志
logResult(request, response, failureCause, asyncManager);
// 发布ServletRequestHandledEvent请求处理完成事件
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}

DispatcherServlet#doService

定位: org.springframework.web.servlet.DispatcherServlet#doService

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
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 如果日志级别为 DEBUG,则打印请求日志
logRequest(request);

// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
// 当include请求时对request的Attribute做快照备份
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}

// Make framework objects available to handlers and view objects.
// 设置Spring框架中的常用对象到request属性中,这四个属性会在handler和view中使用
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

// FlashMap的相关配置,主要用于Redirect转发时参数的传递,此处有一个应用场景:如果post请求是提交表单,提交完之后redirect到一个显示订单的页面,
// 此时需要知道一些订单的信息,但redirect本身没有提交参数的功能,如果想传递参数,那么就必须要写到url,而url有长度的限制同时还容易对外暴露,此时
// 可以使用flashMap来传递参数,
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
// 执行请求的分发
doDispatch(request, response);
}
finally {
// 异步处理相关
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
// 还原request快照的属性
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}

DispatcherServlet#doDispatch

定位: org.springframework.web.servlet.DispatcherServlet#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
104
105
106
107
108
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 实际处理时所用的request,如果不是上传请求,则直接使用接收到的request,否则封装成上传类型的request
HttpServletRequest processedRequest = request;
// 处理请求的处理器链(包含处理器和对应的interceptor)
HandlerExecutionChain mappedHandler = null;
// 是不是上传请求的标志
boolean multipartRequestParsed = false;

// 获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
// 封装model和view的容器
ModelAndView mv = null;
// 处理请求过程中抛出的异常,但是不包含渲染过程中抛出的异常
Exception dispatchException = null;

try {
// 检测请求是否为上传请求,如果是则通过multipartResolver将其封装成MultipartHttpServletRequest对象
processedRequest = checkMultipart(request);
// 设置上传请求的标志
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
// 获得请求对应的HandlerExecutionChain对象(HandlerMethod和HandlerInterceptor拦截器们)
mappedHandler = getHandler(processedRequest);
// 如果获取不到,则根据配置抛出异常或返回404错误
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.
// 处理GET、HEAD请求的Last-Modified,当浏览器第一次跟服务器请求资源时,服务器会在返回的请求头里包含一个last_modified的属性,
// 代表资源最后时什么时候修改的,在浏览器以后发送请求的时候,会同时发送之前接收到的Last_modified.服务器接收到带last_modified的请求后,
// 会跟实际资源的最后修改时间做对比,如果过期了返回新的资源,否则直接返回304表示未过期,直接使用之前缓存的结果即可
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;
}
}

// 执行响应的Interceptor的preHandler
// 注意:该方法如果有一个拦截器的前置处理返回false,则开始倒序触发所有的拦截器的 已完成处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// Actually invoke the handler.
// 真正的调用handler方法,也就是执行对应的方法,并返回视图
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

// 如果需要异步处理,直接返回
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}

// 当view为空时,根据request设置默认的view
applyDefaultViewName(processedRequest, mv);
// 执行响应的interceptor的postHandler方法
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);
}
// 处理返回结果,包括处理异常、渲染页面、触发Interceptor的afterCompletion
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 已完成处理 拦截器
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
// 完成处理激活触发器
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.
// 删除上传请求的资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}