第2步處理方法:
//遍歷所有的映射器,直到找到能夠配對該請求的一個映射器,
// 在映射器內部配對到對應的Handler,最終生成HandlerExecutionChain對象並返回
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
//this.handlerMappings在容器初始化時已經生成
//主要看下:HandlerExecutionChain handler = hm.getHandler(request);
getHandler在HandlerMapping接口中
public interface HandlerMapping{
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
HandlerMapping接口中getHandler實現類如下:
AbstractHandlerMapping類中實現getHandler方法:
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//抽象類的抽象方法,匹配對象請求的Handler對象,具體實現邏輯看子類
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
//如果匹配的Handler對象只是字符串,則以字符串爲id。例如容器中得到對象的bean
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//將匹配的攔截器和Handler對象全部都包裝到HandlerExecutionChain對象中
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;
}
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
getHandler裏面有兩個方法:
2.1.//抽象類的抽象方法,匹配對象請求的Handler對象,具體實現邏輯看子類
Object handler = getHandlerInternal(request);
2.2//將匹配的攔截器和Handler對象全部都包裝到HandlerExecutionChain對象中
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
先看2.1:
Object handler = getHandlerInternal(request);
AbstractHandlerMapping中有接口:
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
getHandlerInternal接口實現類分爲兩個類:
AbstractUrlHandlerMapping //實現url匹配controller
AbstractHandlerMethodMapping //實現Method匹配方法
首先看AbstractUrlHandlerMapping實現方法:
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//根據請求獲取路徑
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//根據路徑獲取Handler
Object handler = lookupHandler(lookupPath, request);
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)) {
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 {
// Direct match?
//直接嘗試匹配
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// Bean name or resolved handler?
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()) {
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<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
Collections.sort(matchingPatterns, 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 + "]");
}
}
// Bean name or resolved handler?
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);
}
}
if (logger.isDebugEnabled()) {
logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
}
// No handler found...
return null;
}
現在看第二種實現方式:AbstractHandlerMethodMapping
在容器初始化過程中創建映射器(RequestMappingHandlerMapping)對象時,
會尋找所有被@Controller 註解類中被 @RequestMapping 註解的方法,
然後解析方法上的 @RequestMapping 註解,把解析結果封裝成 RequestMappingInfo 對象,
也就是說RequestMappingInfo 對象是用來裝載方法的匹配相關信息,
每個匹配的方法都會對應一個 RequestMappingInfo 對象。
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<Match> matches = new ArrayList<>();
//根據請求的lookupPath,找到對應的記錄映射方法信息的對象的數組,也就是List<T>
//當實現類是RequestMappingHandlerMapping時,T就是RequestMappingInfo
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...
//有時候根據lookupPath匹配不了對應的方法記錄信息,例如restful風格/test/{username}
//但是實際lookupPath=/test/tom,這樣就需要遍歷所有的Mappings
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
//getMappingComparator(request) 該抽象類的抽象方法,如果最終一個request匹配出多個
//RequestMappingInfo,那麼最終由實現類自己實現排序邏輯
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 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
//遍歷所有的mapping,也就會上面的List<RequestMappingInfo>
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
//該抽象類的抽象方法,由實現類自己實現檢測邏輯,
// 匹配request對象和RequestMappingInfo上面對應的信息是否匹配,匹配規則自己寫
T match = getMatchingMapping(mapping, request);
if (match != null) {
//將匹配的RequestMappingInfo對象和其對應的HandlerMethod 對象裝進Match對象,放進matches集合裏面
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
2.2//將匹配的攔截器和Handler對象全部都包裝到HandlerExecutionChain對象中
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
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;
}
以上就是第二步的源碼,主要是取得處理當前請求的controller,這裏也稱爲hanlder處理器。