我们常用的@Controller和@RequestMapping注解对应的HandlerMapping类是RequestMappingHandlerMapping,其继承的AbstractHandlerMethodMapping类中缓存了URL到HandlerMethod的映射信息,从RequestMappingHandlerMapping中获取的Handler实际上是HandlerMethod。源码解析如下:
HandlerMapping的getHandler()方法由抽象类AbstractHandlerMapping实现:
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//根据request获取handler,此处handler是HandlerMethod
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 = obtainApplicationContext().getBean(handlerName);
}
//获取执行链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
AbstractHandlerMethodMapping中getHandlerInternal()方法具体实现:
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获取path,从request获取contextPath+RequestUri+RemainingPath
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
//加读锁
this.mappingRegistry.acquireReadLock();
try {
//根据path找HandlerMethod,从mappingRegistry.urlLookup()中根据url找到
//对应的List<RequestMappingInfo>
//遍历RequestMappingInfo,RequestMappingInfo中有各种condition,根据
//request看各个RequestMappingInfo与request是否匹配,匹配的话构造一个新
//的RequestMappingInfo返回,根据新构造的RequestMappingInfo和
//从MappingRegistry.getMappings中根据request获取的HandlerMethod,
//构造Match对象,并加入到List<Match>中。
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();
}
}