1.1 前言

  • 上一章节介绍了 RequestMappingHandlerMapping 这个 HandlerMapping 的加载过程,这一章节来介绍RequestMappingHandlerMapping实现流程

2.1 找到与请求对应的 Handler 解析

  • 还是回到这个方法doDispatch(HttpServletRequest request, HttpServletResponse response) ,下面的代码是发挥RequestMappingHandlerMapping作用的地方
1
2
3
4
5
6
7
8
9
10
HandlerExecutionChain mappedHandler = null;
...

// Determine handler for the current request.
// 遍历所有的 HandlerMapping 找到与请求对应的 Handler,并将其与一堆拦截器封装到 HandlerExecution 对象中
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
  • 进入 getHandler方法,这里会遍历到我们的RequestMappingHandlerMapping 这个HandlerMapping,通过HandlerExecutionChain handler = hm.getHandler(request); 得到HandlerExecutionChain
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 循环handlerMappings eg: RequestMappingHandlerMapping、SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
// 遍历HandlerMapping实现类的找到对应的 HandlerExecutionChain
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
// 注意这里是找到第一个就直接返回
return handler;
}
}
return null;
}
  • 进入hm.getHandler(request); 会跳到我们的AbstractHandlerMapping 类中,RequestMappingHandlerMapping 继承该类,由下面代码可以看到这里这里获取了 handlerInterceptor 并封装为HandlerExecutionChain 返回调用者
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
/**
* Look up a handler for the given request, falling back to the default
* handler if no specific one is found.
* @param request current HTTP request
* @return the corresponding handler instance, or the default handler
* @see #getHandlerInternal
*/
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 在这里获取 处理器handler,模板方法实现, RequestMappingHandlerMapping 跳到 AbstractHandlerMethodMapping
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
// 获取 拦截器Interceptor
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
  • 关注Object handler = getHandlerInternal(request); 这里是获取handler的地方,这时又会跳到AbstractHandlerMethodMapping 类中,这样跳来跳去可以看到封装的特性及使用模板方法提高了扩展性
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
/**
* Look up a handler method for the given request.
*/
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获取请求url路径 localhost:8080/pub/account/list >>> /pub/account/list
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
// mappingRegistry添加读锁,其他线程只能读不能写
this.mappingRegistry.acquireReadLock();
try {
// 根据request获取对应的HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
  • 关注 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); 这行代码,进入该方法,可以看到这个方法的作用是得到HandlerMethod
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
/**
* 查找当前request请求 最为匹配的处理方法HandlerMethod,如果有多个匹配结果,则选择最佳匹配结果
* Look up the best-matching handler method for the current request.
* If multiple matches are found, the best match is selected.
* @param lookupPath mapping lookup path within the current servlet mapping
* @param request the current request
* @return the best-matching handler method, or {@code null} if no match
* @see #handleMatch(Object, String, HttpServletRequest)
* @see #handleNoMatch(Set, String, HttpServletRequest)
*/
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<Match>();
// 根据URL来获取,springMVC会在初始化的时候建立URL和相应RequestMappingInfo的映射。如果不是restful接口,这里就可以直接获取到了, lookupPath: /pub/account/list
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
// 匹配校验
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// 全盘扫描
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
// 得到匹配结果
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
Collections.sort(matches, comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
lookupPath + "] : " + matches);
}
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
// 如果最佳匹配 第二佳匹配都是同一个则报错
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
// 设置HttpServletRequest值
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
// 没有找到匹配,返回null
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
  • 查看这行代码可以看到是通过url来获取this.mappingRegistry.getMappingsByUrl(lookupPath);,进入该方法,可以看到this.urlLookupMappingRegistry类中的一个Map,直接通过 urlkey得到值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MappingRegistry {

private final Map<T, MappingRegistration<T>> registry = new HashMap<T, MappingRegistration<T>>();

private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();

private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();

private final Map<String, List<HandlerMethod>> nameLookup =
new ConcurrentHashMap<String, List<HandlerMethod>>();

private final Map<HandlerMethod, CorsConfiguration> corsLookup =
new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();

private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

...


*/
public List<T> getMappingsByUrl(String urlPath) {
// MultiValueMap<String, T> urlLookup 就是个map
return this.urlLookup.get(urlPath);
}

下图是this.urlLookup.get(urlPath) 的到的结果,返回的是个list

image
image
  • 返回到lookupHandlerMethod(String lookupPath, HttpServletRequest request) 方法,这里使用了Match做了匹配处理,得到最佳Match bestMatch 对象,最后返回HandlerMethod,在此终于得到了HandlerMethod

  • 得到HandlerMethod对象之后,返回到getHandler(HttpServletRequest request)方法中,下面主要逻辑是整合了HandlerMethodHandlerInterceptor并存放在HandlerExecutionChain对象

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
/**
* Look up a handler for the given request, falling back to the default
* handler if no specific one is found.
* @param request current HTTP request
* @return the corresponding handler instance, or the default handler
* @see #getHandlerInternal
*/
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 在这里获取 处理器handler,模板方法实现, RequestMappingHandlerMapping 跳到 AbstractHandlerMethodMapping
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
// 获取 拦截器Interceptor
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}

3.1 总结

  • RequestMappingHandlerMapping 的主要功能就是通过 reqeust 获取 HandlerExecutionChainHandlerMethodInterceptor

  • 下图是RequestMappingHandlerMapping工作流程图,可以看到RequestMappingHandlerMapping 一个类的实现分了4层,HandlerMapping 接口定义顶级方法,两个抽象类又分两次封装,由上而下,逐渐细分功能

image
image

4.1 参考

官方文档: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html