HandlerMapping家族成员可以分为两支,一支继承自AbastractUrlHandlerMapping,另一支继承自AbastracHandlerMethodMapping,两只都继承自AbastractHandlerMapping。
绿框 AbstractHandlerMapping 抽象类,实现了【获得请求对应的处理器和拦截器们】的骨架逻辑,然后提供 getHandlerInternal(HttpServletRequest request)
模板方法,交由子类实现。
AbstractHandlerMapping 的子类:
红框 AbstractUrlHandlerMapping 系,基于 URL 进行匹配。当然,实际我们开发时,这种方式已经基本不用了,被 @RequestMapping
等注解的方式所取代。不过,Spring MVC 内置的一些路径匹配,还是使用这种方式。
黄框 AbstractHandlerMethodMapping 系,基于 Method 进行匹配。例如,我们所熟知的 @RequestMapping
等注解的方式。
白框 MatchableHandlerMapping 接口,定义判断请求和指定 pattern
路径是否匹配的接口方法。
AbstractHandlerMapping
AbstractHandlerMapping采用模板模式设计了HandlerMapping的整体结构,然后子类通过实现模板方法提供一些初始值和具体算法即可。AbstractHandlerMapping继承了WebApplicationObjectSupport,初始化时会调用模板方法initApplicationContext,即AbstractHandlerMapping的创建就是在initApplicationContext中实现。
// AbstractHandlerMapping.java
@Override
protected void initApplicationContext() throws BeansException {
// 空方法。交给子类实现,用于注册自定义的拦截器到 interceptors 中。目前暂无子类实现。
extendInterceptors(this.interceptors);
// 扫描已注册的 MappedInterceptor 的 Bean 们,添加到 mappedInterceptors 中
detectMappedInterceptors(this.adaptedInterceptors);
// 将 interceptors 初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors 中
initInterceptors();
}
detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors)
方法,扫描已注册的 MappedInterceptor 的 Bean 们,添加到 mappedInterceptors
中。代码如下:
// AbstractHandlerMapping.java
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
// 扫描已注册的 MappedInterceptor 的 Bean 们,添加到 mappedInterceptors 中
// MappedInterceptor 会根据请求路径做匹配,是否进行拦截。
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}
initInterceptors()
方法,将 interceptors
初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors
中。代码如下:
// AbstractHandlerMapping.java
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
// 遍历 interceptors 数组
for (int i = 0; i < this.interceptors.size(); i++) {
// 获得 interceptor 对象
Object interceptor = this.interceptors.get(i);
if (interceptor == null) { // 若为空,抛出 IllegalArgumentException 异常
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
// 将 interceptors 初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors 中
// 注意,HandlerInterceptor 无需进行路径匹配,直接拦截全部
this.adaptedInterceptors.add(adaptInterceptor(interceptor)); // <x>
}
}
}
可以看到AbstractHandlerMapping保存了所有Interceptor,其属性有两个List类型的Interceptor
/**
* 配置的拦截器数组,并不会直接使用
*
* 而是在 {@link #initInterceptors()} 方法中,初始化到 {@link #adaptedInterceptors} 中使用
*
* 添加方式有两种:
*
* 1. {@link #setInterceptors(Object...)} 方法
* 2. {@link #extendInterceptors(List)} 方法
*/
private final List<Object> interceptors = new ArrayList<>();
/**
* 初始化后的拦截器 HandlerInterceptor 数组,使用时与Url匹配
*/
private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();
初始化完成后,我们来看如何获取Handler和Interceptor。getHandler(HttpServletRequest request)
方法,获得请求对应的 HandlerExecutionChain 对象。代码如下:
// DispatcherServlet.java
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
// 遍历 HandlerMapping 数组
for (HandlerMapping mapping : this.handlerMappings) {
// 获得请求对应的 HandlerExecutionChain 对象
HandlerExecutionChain handler = mapping.getHandler(request);
// 获得到,则返回
if (handler != null) {
return handler;
}
}
}
return null;
}
// AbstractHandlerMapping.java
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// <1> 获得处理器。该方法是抽象方法,由子类实现
Object handler = getHandlerInternal(request);
// <2> 获得不到,则使用默认处理器
if (handler == null) {
handler = getDefaultHandler();
}
// <3> 还是获得不到,则返回 null
if (handler == null) {
return null;
}
// Bean name or resolved handler?
// <4> 如果找到的处理器是 String 类型,则从容器中找到 String 对应的 Bean 类型作为处理器。
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// <5> 获得 HandlerExecutionChain 对象
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
// <7> 返回
return executionChain;
}
getHandlerExecutionChain(Object handler, HttpServletRequest request)
方法,获得 HandlerExecutionChain 对象。代码如下:
// AbstractHandlerMapping.java
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
// 创建 HandlerExecutionChain 对象
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
// 获得请求路径
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
// 遍历 adaptedInterceptors 数组,获得请求匹配的拦截器
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
// 需要匹配,若路径匹配,则添加到 chain 中
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { // 匹配
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
// 无需匹配,直接添加到 chain 中
} else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
AbstractHandlerMethodMapping
AbstractHandlerMethodMapping
,实现 InitializingBean 接口,继承 AbstractHandlerMapping 抽象类,以 Method 作为 Handler 的 HandlerMapping 抽象类,提供 Mapping 的初始化、注册等通用的骨架方法。这就是我们常说的模板方法模式。
// AbstractHandlerMethodMapping.java
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
/**
* Mapping 注册表
*/
private final MappingRegistry mappingRegistry = new MappingRegistry();
/**
* Mapping 命名策略
*/
@Nullable
private HandlerMethodMappingNamingStrategy<T> namingStrategy;
}
泛型T代表匹配Handler的条件而专门使用的一种类,这里的条件就不只是url,还包含如Request类型(get、post),请求参数、Head等都可以作为匹配Handler的条件。默认是用RequestMappingInfo。
MappingRegistry ,是 AbstractHandlerMethodMapping 的私有类,Mapping 注册表。
// AbstractHandlerMethodMapping.java#MappingRegistry
/**
* 注册表
*
* KEY: MappingInfo
*/
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
/**
* 注册表 保存着匹配条件(RequestCondition)和HandlerMethod的对应关系
*
* KEY:MappingInfo
*/
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
/**
* 直接 URL 的映射,保存着Url与匹配条件(RequestCondition)对应关系
*
* KEY:直接 URL
* VALUE:MappingInfo 数组
*/
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
/**
* MappingInfo 的名字与 HandlerMethod 的映射
*
* KEY:Mapping 的名字
* VALUE:HandlerMethod 数组
*/
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
/**
* cors
*/
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
/**
* 读写锁
*/
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
初始化
了解一些关键属性后,我们来看它的初始化,AbstractHandlerMapping 实现 InitializingBean接口,spring容器调用其afterPropertiesSet()方法进行初始化。
// AbstractHandlerMethodMapping.java
/**
* 是否只扫描可访问的 HandlerMethod 们
*/
private boolean detectHandlerMethodsInAncestorContexts = false;
@Override
public void afterPropertiesSet() {
// <x> 初始化处理器的方法们
initHandlerMethods();
}
/**
* Scan beans in the ApplicationContext, detect and register handler methods.
* @see #getCandidateBeanNames()
* @see #processCandidateBean
* @see #handlerMethodsInitialized
*/
protected void initHandlerMethods() {
//遍历 Bean ,逐个处理
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
// <1.2> 处理 Bean
processCandidateBean(beanName);
}
}
//初始化处理器的方法们。目前是空方法,暂无具体的实现
handlerMethodsInitialized(getHandlerMethods());
}
getCandidateBeanNames()
方法,获得所有 Bean 的名字们,然后进行遍历处理。
// AbstractHandlerMethodMapping.java
/**
* Determine the names of candidate beans in the application context.
* @since 5.1
* @see #setDetectHandlerMethodsInAncestorContexts
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors
*/
protected String[] getCandidateBeanNames() {
return (this.detectHandlerMethodsInAncestorContexts ? // 可访问
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
obtainApplicationContext().getBeanNamesForType(Object.class));
}
processCandidateBean(String beanName)
方法,判断 Bean 是否为处理器,如果是,则扫描处理器方法。代码如下:
// AbstractHandlerMethodMapping.java
/**
* Determine the type of the specified candidate bean and call
* {@link #detectHandlerMethods} if identified as a handler type.
* <p>This implementation avoids bean creation through checking
* {@link org.springframework.beans.factory.BeanFactory#getType}
* and calling {@link #detectHandlerMethods} with the bean name.
* @param beanName the name of the candidate bean
* @since 5.1
* @see #isHandler
* @see #detectHandlerMethods
*/
protected void processCandidateBean(String beanName) {
// <1> 获得 Bean 对应的类型
Class<?> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
} catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
// 判断 Bean 是否为处理器,如果是,则扫描处理器方法
if (beanType != null && isHandler(beanType)) { // <2.1>
detectHandlerMethods(beanName); // <2.2>
}
}
调用 #isHandler(Class<?> beanType)
抽象方法,判断 Bean 的类型是否为处理器,具体实现在RequestMappingHandlerMapping
@Override
protected boolean isHandler(Class<?> beanType) {
//判断类上@Controller注解,或方法上RequestMapping注解
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
detectHandlerMethods初始化处理器的方法们。代码如下:
// AbstractHandlerMethodMapping.java
/**
* Look for handler methods in a handler.
* @param handler the bean name of a handler or a handler instance
*/
protected void detectHandlerMethods(final Object handler) {
// <1> 获得处理器类型
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// <2> 获得真实的类。因为,handlerType 可能是代理类
final Class<?> userType = ClassUtils.getUserClass(handlerType);
// <3> 获得匹配的方法的集合
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> getMappingForMethod(method, userType)); // 抽象方法,子类实现
if (logger.isTraceEnabled()) {
logger.trace("Mapped " + methods.size() + " handler method(s) for " + userType + ": " + methods);
}
// <4> 遍历方法,逐个注册 HandlerMethod
methods.forEach((key, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(key, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
#getMappingForMethod(Method method, Class<?> handlerType)
方法,获得方法上的 RequestMappingInfo 对象,基于 @RequestMapping
构造。代码如下:
// RequestMappingHandlerMapping.java
/**
* Uses method and type-level @{@link RequestMapping} annotations to create
* the RequestMappingInfo.
* @return the created RequestMappingInfo, or {@code null} if the method
* does not have a {@code @RequestMapping} annotation.
* @see #getCustomMethodCondition(Method)
* @see #getCustomTypeCondition(Class)
*/
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
// <1> 基于方法上的 @RequestMapping 注解,创建 RequestMappingInfo 对象
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
// <2> 基于类上的 @RequestMapping 注解,合并进去
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
// <3> 如果有前缀,则设置到 info 中
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).build().combine(info);
}
}
return info;
}
#registerHandlerMethod(Object handler, Method method, T mapping)
方法,注册 HandlerMethod
// AbstractHandlerMethodMapping.java
/**
* 注册 HandlerMethod
*
* Register a handler method and its unique mapping. Invoked at startup for
* each detected handler method.
* @param handler the bean name of the handler or the handler instance
* @param method the method to register
* @param mapping the mapping conditions associated with the handler method
* @throws IllegalStateException if another method was already registered
* under the same mapping
*/
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
// AbstractHandlerMethodMapping.java#MappingRegistry
public void register(T mapping, Object handler, Method method) {
// <1> 获得写锁
this.readWriteLock.writeLock().lock();
try {
// <2.1> 创建 HandlerMethod 对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
// <2.2> 校验当前 mapping 不存在,否则抛出 IllegalStateException 异常
assertUniqueMethodMapping(handlerMethod, mapping);
// <2.3> 添加 mapping + HandlerMethod 到 mappingLookup 中
this.mappingLookup.put(mapping, handlerMethod);
// <3.1> 获得 mapping 对应的普通 URL 数组
List<String> directUrls = getDirectUrls(mapping);
// <3.2> 添加到 url + mapping 到 urlLookup 集合中
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
// <4> 初始化 nameLookup
String name = null;
if (getNamingStrategy() != null) {
// <4.1> 获得 Mapping 的名字
name = getNamingStrategy().getName(handlerMethod, mapping);
// <4.2> 添加到 mapping 的名字 + HandlerMethod 到 nameLookup 中
addMappingName(name, handlerMethod);
}
// <5> TODO 1012 cors
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
// <6> 创建 MappingRegistration 对象,并 mapping + MappingRegistration 添加到 registry 中
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod));
} finally {
// <7> 释放写锁
this.readWriteLock.writeLock().unlock();
}
}
使用
getHandlerInternal(ServerWebExchange exchange)
方法,获得请求对应的 HandlerMethod 对象。代码如下:
// AbstractHandlerMethodMapping.java
/**
* Look up a handler method for the given request.
*/
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获得请求的路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
// 获得读锁
this.mappingRegistry.acquireReadLock();
try {
// 获得 HandlerMethod 对象
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
// 进一步,获得 HandlerMethod 对象
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
} finally {
// 释放读锁
this.mappingRegistry.releaseReadLock();
}
}
调用 #lookupHandlerMethod(ServerWebExchange exchange)
方法,获得 HandlerMethod 对象。
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
// <1> 存储匹配上当前请求的结果
List<Match> matches = new ArrayList<>();
// <1.1> 优先,基于直接 URL 的 Mapping 们,进行匹配
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
// <1.2> 如果不能直接使用looupPath得到匹配条件,扫描所有注册表的 Mapping 们,进行匹配
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
// <2> 如果匹配到,则获取最佳匹配的 Match 对象的 handlerMethod 属性
if (!matches.isEmpty()) {
// <2.1> 创建 MatchComparator 对象,排序 matches 结果
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
// <2.2> 获得首个 Match 对象
Match bestMatch = matches.get(0);
// <2.3> 处理存在多个 Match 对象的情况!!
if (matches.size() > 1) {
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
// 比较 bestMatch 和 secondBestMatch ,如果相等,说明有问题,抛出 IllegalStateException 异常
// 因为,两个优先级一样高,说明无法判断谁更优先
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
// <2.4> 处理首个 Match 对象
handleMatch(bestMatch.mapping, lookupPath, request);
// <2.5> 返回首个 Match 对象的 handlerMethod 属性
return bestMatch.handlerMethod;
// <3> 如果匹配不到,则处理不匹配的情况
} else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
整个过程中使用Match作为载体,Match是个内部类,封装了匹配条件和HandlerMothd两个属性。
addMatchingMappings(Collection<T> mappings, List<Match> matches, ServerWebExchange exchange)
方法,将当前请求和注册表中的 Mapping 进行匹配。若匹配成功,则生成 Mapping 记录,添加到 matches
中。代码如下:
// AbstractHandlerMethodMapping.java
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, ServerWebExchange exchange) {
// 遍历 Mapping 数组
for (T mapping : mappings) {
// <1> 执行匹配
T match = getMatchingMapping(mapping, exchange);
// <2> 如果匹配,则创建 Match 对象,添加到 matches 中
if (match != null) {
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
其中getMatchingMapping(T mapping, HttpServletRequest request),由子类RequestMappingInfoHandlerMapping实现
@Override
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
return info.getMatchingCondition(request);
}
RequestMappingInfo
// RequestMappingInfo.java
/**
* 名字
*/
@Nullable
private final String name;
/**
* 请求路径的条件
*/
private final PatternsRequestCondition patternsCondition;
/**
* 请求方法的条件
*/
private final RequestMethodsRequestCondition methodsCondition;
/**
* 参数的条件
*/
private final ParamsRequestCondition paramsCondition;
/**
* 请求头的条件
*/
private final HeadersRequestCondition headersCondition;
/**
* 可消费的 Content-Type 的条件
*/
private final ConsumesRequestCondition consumesCondition;
/**
* 可生产的 Content-Type 的条件
*/
private final ProducesRequestCondition producesCondition;
/**
* 自定义的条件
*/
private final RequestConditionHolder customConditionHolder;
#getMatchingCondition(HttpServletRequest request)
方法,从当前 RequestMappingInfo 获得匹配的条件。如果匹配,则基于其匹配的条件,创建新的 RequestMappingInfo 对象。如果不匹配,则返回 null
。代码如下:
@SuppressWarnings("Duplicates")
@Override
@Nullable
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
// 匹配 methodsCondition、paramsCondition、headersCondition、consumesCondition、producesCondition
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
// 如果任一为空,则返回 null ,表示匹配失败
if (methods == null || params == null || headers == null || consumes == null || produces == null) {
return null;
}
// 匹配 patternsCondition
PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
if (patterns == null) { // 如果 patterns 为空,则返回 null ,表示匹配失败
return null;
}
// 匹配 customConditionHolder
RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
if (custom == null) { // 如果 custom 为空,则返回 null ,表示匹配失败
return null;
}
// 创建匹配的 RequestMappingInfo 对象。
// 为什么要创建 RequestMappingInfo 对象呢?因为当前 RequestMappingInfo 对象,一个 methodsCondition 可以配置 GET、POST、DELETE 等等条件,但是实际就匹配一个请求类型,此时 methods 只代表其匹配的那个。
return new RequestMappingInfo(this.name, patterns,
methods, params, headers, consumes, produces, custom.getCondition());
}
#compareTo(RequestMappingInfo other, HttpServletRequest request)
方法,比较优先级。代码如下:
// RequestMappingInfo.java
/**
* Compares "this" info (i.e. the current instance) with another info in the context of a request.
* <p>Note: It is assumed both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} to ensure they have conditions with
* content relevant to current request.
*/
@Override
public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
int result;
// Automatic vs explicit HTTP HEAD mapping
// 针对 HEAD 请求方法,特殊处理
if (HttpMethod.HEAD.matches(request.getMethod())) {
result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
if (result != 0) {
return result;
}
}
// 比较 patternsCondition
result = this.patternsCondition.compareTo(other.getPatternsCondition(), request);
if (result != 0) {
return result;
}
// 比较 paramsCondition
result = this.paramsCondition.compareTo(other.getParamsCondition(), request);
if (result != 0) {
return result;
}
// 比较 headersCondition
result = this.headersCondition.compareTo(other.getHeadersCondition(), request);
if (result != 0) {
return result;
}
// 比较 consumesCondition
result = this.consumesCondition.compareTo(other.getConsumesCondition(), request);
if (result != 0) {
return result;
}
// 比较 producesCondition
result = this.producesCondition.compareTo(other.getProducesCondition(), request);
if (result != 0) {
return result;
}
// Implicit (no method) vs explicit HTTP method mappings
// 比较 methodsCondition
result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
if (result != 0) {
return result;
}
// 比较 customConditionHolder
result = this.customConditionHolder.compareTo(other.customConditionHolder, request);
if (result != 0) {
return result;
}
return 0;
}
虽然代码非常长,实际都是按照优先级,逐个调用每个属性对应的 #compareTo(RequestMethodsRequestCondition other, HttpServletRequest request)
方法,直到比到不相等