SpringMVC(三):HandlerMapping

继承关系图:

HandlerMapping的作用是根据请求URL找到对应的Handler也就是Controller。

HandlerMapping是一个接口,在接口中定义了一个getHandler方法,通过这个方法可以获得与HTTP请求对应的HandlerExecutionChain,这个HandlerExecutionChain中封装了具体的Controller对象,还设置了一个拦截器链,通过这个拦截器链中的拦截器可以为Handler对象提供功能的增强。

1
2
3
4
5
6
7
8
9
10
11
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

@Nullable
HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
}

一、Handler的注册

1.SimpleUrlHandlerMapping

以SimpleUrlHandlerMapping为例,看一下Hanlder的注册过程。

(1)持有了一个urlMap字段,保存URL和Hanlder的映射关系。

(2)Hanlder的注册过程是在initApplicationContext方法中调用的。initApplicationContext方法中先调用了父类AbstractUrlHandlerMapping 的initApplicationContext方法,这个方法中主要是对拦截器相关的设置。然后调用了registerHandlers方法注册handler。

(3)在registerHandlers方法中,调用了父类AbstractUrlHandlerMapping的registerHandler方法对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
41
42
43
44
45
46
47
48
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
// 保存URL和Hanlder的映射关系
private final Map<String, Object> urlMap = new LinkedHashMap();

public SimpleUrlHandlerMapping() {
}

public void setMappings(Properties mappings) {
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}

public void setUrlMap(Map<String, ?> urlMap) {
this.urlMap.putAll(urlMap);
}

public Map<String, ?> getUrlMap() {
return this.urlMap;
}

// 初始化ApplicationContext
public void initApplicationContext() throws BeansException {
// 调用了AbstractHandlerMapping的initApplicationContext方法,这个方法主要初始化拦截器相关的东西
super.initApplicationContext();
// 注册handler
this.registerHandlers(this.urlMap);
}

// 注册handler,建立URL和controller之间的映射关系
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if(urlMap.isEmpty()) {
this.logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
} else {
// 获取所有的URL和对应的hanlder
urlMap.forEach((url, handler) -> {
if(!url.startsWith("/")) {
url = "/" + url;
}

if(handler instanceof String) {
handler = ((String)handler).trim();
}
// 调用父类的registerHandler完成注册
this.registerHandler(url, handler);
});
}

}
}
2.AbstractUrlHandlerMapping

(1)在AbstractUrlHandlerMapping中,同样持有了一个保存URL和Handler映射关系的字段handlerMap。

(2)在registerHandler方法中:

  • 首先设置一个变量resolvedHandler,将当前传入的handler赋给它;
  • 接着判断是否根据bean名称进行映射,如果是将会直接从容器中获取Handler赋给resolvedHandler;
  • 创建变量mappedHandler,表示是从handlerMap根据URL获取的Handler;如果mappedHandler不为空,会与从容器中根据bean获取的Handler对比是否一致,如果不一致将会报错。
  • 如果mappedHandler为空,说明Handler还未注册,会判断URL是否是’/‘或者’/*’,并分别设置到ROOT或者DefaultHandler中,如果只是普通的URL,因为还没有注册Handler,就把resolvedHandler注册到handlerMap中。
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
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {

// 保存URL和Handler的映射关系,key为URL,value为对应的Handler也就是Controller
private final Map<String, Object> handlerMap = new LinkedHashMap();

// 根据url注册handler
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
Assert.notNull(urlPaths, "URL path array must not be null");
String[] var3 = urlPaths;
int var4 = urlPaths.length;

for(int var5 = 0; var5 < var4; ++var5) {
String urlPath = var3[var5];
this.registerHandler((String)urlPath, (Object)beanName);
}

}

// 注册handler
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;
// 使用bean名称进行映射
if(!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String)handler;
ApplicationContext applicationContext = this.obtainApplicationContext();
if(applicationContext.isSingleton(handlerName)) {
// 直接从容器中获取hanldler的bean,也就是controller
resolvedHandler = applicationContext.getBean(handlerName);
}
}
// 根据URL获取controller
Object mappedHandler = this.handlerMap.get(urlPath);
if(mappedHandler != null) { // 如果controller不为空
if(mappedHandler != resolvedHandler) {
throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler) + " mapped.");
}
} else if(urlPath.equals("/")) {// 如果url是"/"
if(this.logger.isInfoEnabled()) {
this.logger.info("Root mapping to " + this.getHandlerDescription(handler));
}
// 将"/"映射的controller设置到rootHandler
this.setRootHandler(resolvedHandler);
} else if(urlPath.equals("/*")) { // 如果是"/*"
if(this.logger.isInfoEnabled()) {
this.logger.info("Default mapping to " + this.getHandlerDescription(handler));
}
// 将"/*"映射的controller设置到defaultHandler
this.setDefaultHandler(resolvedHandler);
} else {
// 处理正常的URL映射,将当前传入设置handler的key和value,分别对应URL和映射的controller
this.handlerMap.put(urlPath, resolvedHandler);
if(this.logger.isInfoEnabled()) {
this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler));
}
}

}
}

二、Handler的查找过程

1.DispatcherServlet

回到DispatcherServlet,对HTTP请求的处理是在doService中完成的,那么就从这个方法入手,看一下DispatcherServlet是如何根据请求获取对应的Handler(Controller)处理HTTP请求的。

(1)在doService方法中会调用doDispatch方法,这里是分发请求的入口。

(2)在doDispatch方法中,调用了自己的getHandler根据请求获取对应的HandlerExecutionChain,在getHandler方法中遍历handlerMappings寻找对应的HandlerExecutionChain,具体的查找过程由子类实现,在子类的getHandler方法中完成。

1
2
// 根据请求得到对应的HandlerExecutionChain
mappedHandler = this.getHandler(processedRequest);
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
@Nullable
private List<HandlerMapping> handlerMappings;

// 获取handler的方法
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//遍历handlerMappings
if(this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();

while(var2.hasNext()) {
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
//根据当前请求获取HandlerExecutionChain,这里的getHandler方法由子类实现
HandlerExecutionChain handler = hm.getHandler(request);
if(handler != null) {
return handler;
}
}
}

return null;
}

(3)HandlerExecutionChain获取成功后,会调用getHandlerAdapter方法获取HandlerAdapter,最后由HandlerAdapter调用handle方法处理请求。

1
2
3
4
5
6
7
8
//获取HandlerAdapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

......


// 处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

整体代码:

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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
public class DispatcherServlet extends FrameworkServlet {

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(this.logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":"";
this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}

Map<String, Object> attributesSnapshot = null;
if(WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration attrNames = request.getAttributeNames();

label112:
while(true) {
String attrName;
do {
if(!attrNames.hasMoreElements()) {
break label112;
}

attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));

attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}

request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
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 {
// 这里是分发请求的入口
this.doDispatch(request, response);
} finally {
if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}

}

}

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
try {
// 这个ModelAndView持有handler处理请求的结果
ModelAndView mv = null;
Object dispatchException = null;

try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 根据请求得到对应的HandlerExecutionChain
mappedHandler = this.getHandler(processedRequest);
if(mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//获取HandlerAdapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if(isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}

if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}

if(!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if(asyncManager.isConcurrentHandlingStarted()) {
return;
}

this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}

} finally {
if(asyncManager.isConcurrentHandlingStarted()) {
if(mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if(multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}

}
}

@Nullable
private List<HandlerMapping> handlerMappings;

// 获取handler的方法
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//遍历handlerMappings
if(this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();

while(var2.hasNext()) {
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
//根据当前请求获取HandlerExecutionChain,这里的getHandler方法由子类实现
HandlerExecutionChain handler = hm.getHandler(request);
if(handler != null) {
return handler;
}
}
}

return null;
}

// 获取HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if(this.handlerAdapters != null) {
Iterator var2 = this.handlerAdapters.iterator();

while(var2.hasNext()) {
HandlerAdapter ha = (HandlerAdapter)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler adapter [" + ha + "]");
}

if(ha.supports(handler)) {
return ha;
}
}
}

throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
}

以SimpleControllerHandlerAdapter为例,看一下Adapter处理请求的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public SimpleControllerHandlerAdapter() {
}

public boolean supports(Object handler) {
return handler instanceof Controller;
}

@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 处理HTTP请求
return ((Controller)handler).handleRequest(request, response);
}

public long getLastModified(HttpServletRequest request, Object handler) {
return handler instanceof LastModified?((LastModified)handler).getLastModified(request):-1L;
}
}
2.AbstractHandlerMapping

在上一步中,getHandler获取HandlerExecutionChain的过程由子类实现的,同样以SimpleUrlHandlerMapping为例,由继承关系图可知AbstractHandlerMapping是SimpleUrlHandlerMapping的父类,getHandler是在父类中实现的,那么就从AbstractHandlerMapping入手看一下AbstractHandlerMapping中是如何获取HandlerExecutionChain的。

(1)在getHandler方法中,首先调用了getHandlerInternal方法,获取Handler,这个方法是在AbstractUrlHandlerMapping中实现的。

(2)Handler获取之后,将Handler封装到了HandlerExecutionChain中并返回,HandlerExecutionChain中包含了Controller的定义和一个拦截器链。

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
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {

@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取Handler
Object handler = this.getHandlerInternal(request);
// 使用默认的Handler
if(handler == null) {
handler = this.getDefaultHandler();
}

if(handler == null) {
return null;
} else {
if(handler instanceof String) {
// 根据bean名称从容器中获取handler
String handlerName = (String)handler;
handler = this.obtainApplicationContext().getBean(handlerName);
}
// 把handler封装到HandlerExecutionChain中
HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
if(CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
CorsConfiguration config = globalConfig != null?globalConfig.combine(handlerConfig):handlerConfig;
executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
}

return executionChain;
}
}

// 获取HandlerExecutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain?(HandlerExecutionChain)handler:new HandlerExecutionChain(handler);
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Iterator var5 = this.adaptedInterceptors.iterator();
// 添加拦截器
while(var5.hasNext()) {
HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
if(interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
if(mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
chain.addInterceptor(interceptor);
}
}

return chain;
}
}

HandlerExecutionChain中的成员变量:

1
2
3
4
5
6
7
8
9
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
// 处理请求的Controller
private final Object handler;
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
}
3.AbstractUrlHandlerMapping

(1)在AbstractUrlHandlerMapping中的getHandlerInternal方法中调用了lookupHandler方查找当前请求对应的Handler。

(2)查找Handler之后判断是否为空,如果为空,判断当前请求是否是”/“,如果是就使用RootHandler,如果RootHandler也为空,就使用默认的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
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
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {

// 获取Handler
@Nullable
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
// 从request中获取URL路径
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
// 寻找URL对应的handler,如果没有找到,返回null
Object handler = this.lookupHandler(lookupPath, request);
if(handler == null) {
Object rawHandler = null;
// 如果是 "/"
if("/".equals(lookupPath)) {
rawHandler = this.getRootHandler();
}

if(rawHandler == null) {
rawHandler = this.getDefaultHandler();
}

if(rawHandler != null) {
if(rawHandler instanceof String) {
String handlerName = (String)rawHandler;
rawHandler = this.obtainApplicationContext().getBean(handlerName);
}
// 验证handler
this.validateHandler(rawHandler, request);
handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null);
}
}

if(handler != null && this.logger.isDebugEnabled()) {
this.logger.debug("Mapping [" + lookupPath + "] to " + handler);
} else if(handler == null && this.logger.isTraceEnabled()) {
this.logger.trace("No handler mapping found for [" + lookupPath + "]");
}

return handler;
}

// 根据URL寻找Handler
@Nullable
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// 从map中获取handler
Object handler = this.handlerMap.get(urlPath);
if(handler != null) {
// 如果handler是bean名称,从容器中获取
if(handler instanceof String) {
String handlerName = (String)handler;
handler = this.obtainApplicationContext().getBean(handlerName);
}

this.validateHandler(handler, request);
return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);
} else {
List<String> matchingPatterns = new ArrayList();
Iterator var5 = this.handlerMap.keySet().iterator();

while(var5.hasNext()) {
String registeredPattern = (String)var5.next();
if(this.getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
} else if(this.useTrailingSlashMatch() && !registeredPattern.endsWith("/") && this.getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern + "/");
}
}

String bestMatch = null;
Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
if(!matchingPatterns.isEmpty()) {
matchingPatterns.sort(patternComparator);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}

bestMatch = (String)matchingPatterns.get(0);
}

if(bestMatch != null) {
handler = this.handlerMap.get(bestMatch);
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 + "]");
}
}

String pathWithinMapping;
if(handler instanceof String) {
pathWithinMapping = (String)handler;
handler = this.obtainApplicationContext().getBean(pathWithinMapping);
}

this.validateHandler(handler, request);
pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
Map<String, String> uriTemplateVariables = new LinkedHashMap();
Iterator var9 = matchingPatterns.iterator();

while(var9.hasNext()) {
String matchingPattern = (String)var9.next();
if(patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}

if(this.logger.isDebugEnabled()) {
this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}

return this.buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
} else {
return null;
}
}
}
}

参考:

spring技术内幕:深入解析spring架构与设计原理

SpringMvc的handlerMapping的源码解读

SpringMVC工作原理之二:HandlerMapping和HandlerAdapter

Spring版本:5.0.5