HandlerMapping的结构图
不论是Url注册还是@requestMapping都具有相同的父类。所以整体的查找的模板方法在父类AbstractHandlerMapping中,并且他还实现了查找拦截器的方法。查找Handler的方法也实现了,但具体还是在子类中。
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//根据请求找到handler
//getHandlerInternal模板方法,由子类实现
//RequestMethodHandlerMapping的getHandlerInternal由父类AbstractHandlerMethodMapping实现
//Url那边的getHandlerInternal由他们的父类AbstractUrlHandlerMapping实现
Object handler = getHandlerInternal(request);
//没找到则用默认
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
//判断handler是否是spring类型
if (handler instanceof String) {
String handlerName = (String) handler;
//获取handler类的对象
handler = obtainApplicationContext().getBean(handlerName);
}
//获取拦截器以及handler类的请求方法
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//跨境cors
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;
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//HandlerExecutionChain是handler以及它的拦截器的一个类
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//请求的路径
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
//获取该请求的拦截器集合
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
先看@RequestMapping的注解的是如何实现getHandlerInternal方法。getHandlerInternal对请求路径找到请求执行的条件,然后进行匹配,找到符合的执行条件,然后根据执行条件找到HandlerMethod。
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获取请求路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
//加读锁
this.mappingRegistry.acquireReadLock();
try {
//找到请求处理的方法
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();
}
}
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List matches = new ArrayList<>();
//通过url找到问题处理的条件
List directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
//将匹配条件加入matches中
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
//为空,则将所有匹配条件加入matches中
if (matches.isEmpty()) {
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
//对条件进行比较
Comparator comparator = new MatchComparator(getMappingComparator(request));
//排序
matches.sort(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 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
@RequestMapping的请求查找就完成,Url这边只要是根据Map中保存的url与请求的进行对比,假设找到handler则返回,假设Mp的请求带*这种进行处理,然后找到handler,然后构建成HandlerExecutionChain(handler跟拦截器)对象。
@Override
@Nullable
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//获取请求路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//查找handler
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
Object rawHandler = null;
if ("/".equals(lookupPath)) {
rawHandler = getRootHandler();
}
if (rawHandler == null) {
rawHandler = getDefaultHandler();
}
if (rawHandler != null) {
// Bean name or resolved handler?
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
rawHandler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(rawHandler, request);
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
if (handler != null && logger.isDebugEnabled()) {
logger.debug("Mapping [" + lookupPath + "] to " + handler);
}
else if (handler == null && logger.isTraceEnabled()) {
logger.trace("No handler mapping found for [" + lookupPath + "]");
}
return handler;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// 从Map中根据url找到handler
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
//查找handler的bean
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
//构建HandlerInterceptor
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}
//对带*的模式与url进行匹配
List matchingPatterns = new ArrayList<>();
for (String registeredPattern : this.handlerMap.keySet()) {
if (getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
else if (useTrailingSlashMatch()) {
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern +"/");
}
}
}
String bestMatch = null;
Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
matchingPatterns.sort(patternComparator);
if (logger.isDebugEnabled()) {
logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}
bestMatch = 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 + "]");
}
}
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
Map uriTemplateVariables = new LinkedHashMap<>();
for (String matchingPattern : matchingPatterns) {
if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (logger.isDebugEnabled()) {
logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
}
return null;
}