SpringMVC的执行流程

MVC模式

顾名思义,SpringMVC框架是基于MVC设置模式设计的,即Model(模型)-View(视图)-Controller(控制)模式。

这个模式认为,应用程序不论简单或复杂,从结构上看,都可以分成三层。

  1. 最上面的一层,是直接面向最终用户的”视图层”(View)。它是提供给用户的操作界面,是程序的外壳。
  2. 最底下的一层,是核心的”数据层”(Model),也就是程序需要操作的数据或信息。
  3. 中间的一层,就是”控制层”(Controller),它负责根据用户从”视图层”输入的指令,选取”数据层”中的数据,然后对其进行相应的操作,产生最终结果。

这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。这样一来,软件就可以实现模块化,修改外观或者变更数据都不用修改其他层,大大方便了维护和升级。

SpringMVC的执行流程

SpringMVC的执行流程可以概括为下图:

本篇论述的比较简单,网上这篇文章写的比较详细可以作为参考:Spring MVC 源码分析 - 一个请求的旅行过程

下面结合源代码和上图来说明:

1. 请求被发送到DispatcherServlet(中央控制器)。

DispatcherServlet是整个控制流程的核心,一般我们在 SpringMVC 项目的 web.xml 文件中都要配置这个 Servlet,并且拦截所有的请求都进入到这个 Servlet ,并且最终由它的 doDispatch(HttpServletRequest request, HttpServletResponse response) 方法来处理这些请求。

web.xml文件中的配置:

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

DispatcherServletdoDispatch方法概览:

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
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
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 {
//检测请求是否为上传请求,如果是则通过 multipartResolver 将其封装成 MultipartHttpServletRequest 对象
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// 获得请求对应的 HandlerExecutionChain 对象(HandlerMethod 和 HandlerInterceptor 拦截器们)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) { //如果获取不到,则根据配置抛出异常或返回 404 错误
noHandlerFound(processedRequest, response);
return;
}

// 获得当前 handler 对应的 HandlerAdapter 对象
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// 处理有Last-Modified请求头的场景
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;
}
}

//执行拦截器们的 preHandler 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

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

//如果是异步,立即返回
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}

//无视图的情况下设置默认视图名称
applyDefaultViewName(processedRequest, mv);

//执行拦截器们的 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);
}

//处理正常和异常的请求调用结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
//processDispatchResult处理异常,则执行拦截器的 afterCompletion 方法。
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
//processDispatchResult处理异常,则执行拦截器的 afterCompletion 方法。
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// 如果是上传请求则清理资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

2.通过HandlerMapping得到HandlerExecutionChain(处理器执行链)

DispatcherServlet找到请求所对应的HandlerMapping实例,再由HandlerMapping获取处理该请求的处理器(handler)、拦截器们(intercepter)列表,并且包装在HandlerExecutionChain对象中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Return the HandlerExecutionChain for this request.
* <p>Tries all handler mappings in order.
* @param request current HTTP request
* @return the HandlerExecutionChain, or {@code null} if no handler could be found
*/
@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;
}

3.获取处理器对应的HandlerAdapter

得到HandlerExecutionChain了后,还不能直接调用处理器,需要进行对处理器进行适配,找到处理器对应的HandlerAdapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Return the HandlerAdapter for this handler object.
* @param handler the handler object to find an adapter for
* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

4.HandlerAdapter调用处理器并返回一个ModelAndView对象

HandlerAdapter通过反射方法调用处理器,处理完成之后返回一个ModelAndView对象,ModelAndView对象中包装了模型数据和视图名称。

5.ViewResolver根据ModelAndView对象的 viewName 解析视图,若能解析成功,返回相应的View视图对象。

ViewResolver会根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Nullable
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
Locale locale, HttpServletRequest request) throws Exception {

if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}

6.最后View视图对象根据ModelAndView对象的 model 渲染视图,并将渲染结果返回给用户。

渲染视图就是将模型数据填充至视图中。springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等,我们最常用的视图就是jsp。

------ 本文完 ------