springMVC流程

DispatcherServlet:

是一个servlet,也就是会被放到tomcat容器中,只不过功能是用来分发。

所有请求,视图解析,映射处理之类的都是通过DispatcherServlet来交给其他组件,最后返回响应给用户。

步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
 1、  首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;

2、 DispatcherServlet——>HandlerMapping,HandlerMapping 将会把请求映射为 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面控制器)对象、多个 HandlerInterceptor 拦截器,handler处理器是通过AbstractUrlHandlerMapping类中的方法来获取的,HandlerInterceptor是通过AbstractHandlerMapping类来获取的)对象,通过这种策略模式,很容易添加新的映射策略;

3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;

4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个 ModelAndView 对象(包含模型数据、逻辑视图名);

5、 ModelAndView 的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的 View,通过这种策略模式,很容易更换其他视图技术;

6、 View——>渲染,View 会根据传进来的 Model 模型数据进行渲染,此处的 Model 实际是一个 Map 数据结构,因此很容易支持其他视图技术;

7、 返回控制权给 DispatcherServlet,由 DispatcherServlet 返回响应给用户,到此一个流程结束。

1554688443636

  1. 设置属性
  2. 根据 Request 请求的 URL 得到对应的 handler 执行链,其实就是拦截器和 Controller 代理对象。
  3. 得到 handler 的适配器
  4. 循环执行 handler 的 pre 拦截器
  5. 执行真正的 handler,并返回 ModelAndView(Handler 是个代理对象,可能会执行 AOP )
  6. 根据 ModelAndView 信息得到 View 实例
  7. 渲染 View 返回

1554689261900

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
//根据url调用不同的handler来处理。
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 {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
//根据request找对应的HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}

// Determine handler adapter for the current request.
//mappedHandler是Chain,里面有handler和interceptor,从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;
}
}
//chain中的所有前处理进行处理。
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// Actually invoke the handler.
//用HandlerAdapter处理请求,得到的是ModelAndView
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) {
//有异常依然会执行afterCOmpletion
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
//Interceptor中的afterCompletion方法
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);
}
}
}
}

AbstractHandlerMapping

获得HandlerExecutionChain,以及拦截器的list。

1个url->多个拦截器。1个url->1个handler.

在AbstractHandlerMapping中,

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
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//抽象方法,在子类中实现。被欢迎页和AbstractUrlHandlerMapping实现了。
Object handler = getHandlerInternal(request);
if (handler == null) {
//用默认的handler
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
//反射调用从ApplicationContext中获得handler.
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//从handler中得到HandlerExecutionChain;
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
………………………………………………

if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}

return executionChain;
}


//Interceptorlist 是在这里被放进去的。因为url可能对应多个Interceptro,所以这里不用找最佳匹配。
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//如果handler是HandlerExecutionChain的子类,直接转换,不是的话放到Chain中的Handler变量中
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
//向HandlerExecutionChain添加拦截器集合。
//this.adaptedInterceptors是在初始化的时候获得,有所有的
//如果是MappedInterceptor,需要将url和设置的过滤条件对比。
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
//pathMatcher工具类。字符串路径匹配。
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}

AbstractUrlHandlerMapping

从url中找出handler,这里找的是handler,和interceptor不一样。主要就是解决模式匹配的问题:/xxx/* 还有一个url匹配多个Map中的key。

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//查找handler
Object handler = lookupHandler(lookupPath, request);
//没有对应的handler
if (handler == null) {
// We need to care for the default handler directly, since we need to
// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
Object rawHandler = null;
if ("/".equals(lookupPath)) {
//rootHandler用来处理"/"
rawHandler = getRootHandler();
}
if (rawHandler == null) {
//默认handler
rawHandler = getDefaultHandler();
}

if (rawHandler != null) {
// Bean name or resolved handler?
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
//应该是根据名字去找handler.
rawHandler = obtainApplicationContext().getBean(handlerName);
}
//检验是否匹配。
validateHandler(rawHandler, request);
//注册拦截器。
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
return handler;
}
-------------------------------------
//查找Handler
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// Direct match?
//直接从map中找
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// Bean name or resolved handler?
//如果是beanname,容器中获取
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//验证
validateHandler(handler, request);
//拦截器
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}

// Pattern match?
//模式匹配
List<String> matchingPatterns = new ArrayList<>();
for (String registeredPattern : this.handlerMap.keySet()) {
//工具包中的matcher,进行匹配。matcher.match(Pattern,path)
if (getPathMatcher().match(registeredPattern, urlPath)) {
//先把满足的加到list中,因为可能有多个。
matchingPatterns.add(registeredPattern);
}
//要不要考虑末尾的斜杠
else if (useTrailingSlashMatch()) {
//
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern +"/");
}
}
}
//从list中找出最匹配的。
String bestMatch = null;
//自定义比较器,比较器的具体实现在AntPathMatcher中
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
//排序
matchingPatterns.sort(patternComparator);

if (logger.isTraceEnabled() && matchingPatterns.size() > 1) {
logger.trace("Matching patterns " + matchingPatterns);
}
//获取第一个
bestMatch = matchingPatterns.get(0);
}
//存在最佳匹配
if (bestMatch != null) {
handler = this.handlerMap.get(bestMatch);
//map中没有对应的handler
if (handler == null) {

if (bestMatch.endsWith("/")) {
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
}
if (handler == null) {
//抛异常
throw new IllegalStateException(
"Could not find handler for best pattern match [" + bestMatch + "]");
}
}
// Bean name or resolved handler?
//多次出现了的语句。map中放的有的是String,(猜测:第一次用,还未初始化??)。
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//检测
validateHandler(handler, request);
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);

// There might be multiple 'best patterns', let's make sure we have the correct URI template variables
// for all of them
//可能有多个最佳匹配。
Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
for (String matchingPattern : matchingPatterns) {
if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
}

// No handler found...
return null;
}
-------------
//用找到的handler构建一个HandlerExecutionChain,并注册两个两个拦截器PathExposingHandlerInterceptor,UriTemplateVariablesHandlerInterceptor

protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {

HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
}
return chain;
}

两个内部拦截器作用:就是将与当前url实际匹配的pattern、匹配条件以及url模板参数等设置到request的属性里面去,这样在后面的处理过程中就可以直接从request属性中获取。

handler可以通过protected void registerHandler(String urlPath, Object 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
28
29
30
31
32
33
34
35
36
37
38
39
40
//部分函数	
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;

// Eagerly resolve handler if referencing singleton via name.
//非懒加载
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
ApplicationContext applicationContext = obtainApplicationContext();
if (applicationContext.isSingleton(handlerName)) {
resolvedHandler = applicationContext.getBean(handlerName);
}
}
Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
//已经有了
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
//“/”注册的是rootHandler
if (urlPath.equals("/"))
setRootHandler(resolvedHandler);
}
// "/*"注册默认handler
else if (urlPath.equals("/*")) {
setDefaultHandler(resolvedHandler);
}
else {
//加进去
this.handlerMap.put(urlPath, resolvedHandler);
}
}
}
}

拦截器

拦截器的实现:

  • 实现HandlerInterceptor
  • 继承实现了HandlerInterceptor接口的类。例如:HandlerInterceptorAdapter

HandlerExecutionChain

1
2
3
4
5
6
7
8
9
private final Object handler;//HandlerMethod

@Nullable
private HandlerInterceptor[] interceptors;

@Nullable
private List<HandlerInterceptor> interceptorList;//存在这里

private int interceptorIndex = -1;

interceptors是在构造函数中直接传入的。最后也会通过CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);加到List中

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
//责任链,返回false,说明不用再往下继续了。之后的controller和interceptor都不用再执行了。直接执行afterCompletion	
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
//直接执行after了。
triggerAfterCompletion(request, response, null);

return false;
}
//最后一个interceptor的位置
this.interceptorIndex = i;
}
}
return true;
}

/**
* Apply postHandle methods of registered interceptors.
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {

HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}

/**
* Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
* Will just invoke afterCompletion for all interceptors whose preHandle invocation
* has successfully completed and returned true.
*/
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {

HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
  • HandlerInterceptorAdapter
    实现了AsyncHandlerInterceptor,多了afterConcurrentHandlingStarted():可以处理异步请求。Controller中有异步请求方法时会触发该方法。一般继承这个抽象类
  • MappedInterceptor 对某些地址进行排除和包括的拦截器。
  • WebInterceptor: 针对请求,参数中没有response,并且没有返回值。

Filter的区别:

  • Interceptor 是SPring的组件,FIlter是在Servlet容器中。javax.servlet包中。
  • FIlter优先于Interceptor执行。
  • 总的来说就是不是同一个东西,但是功能相似。在Spring架构中,优先使用拦截器。

Filter方法:

  • void init(FilterConfig paramFilterConfig)
  • doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) 责任链模式,将Chain传递下去
  • void destroy() 销毁资源。

用途:权限检查。