第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处理器。