本文从类的设计角度分析SpringMVC从RequestMappingHandlerMapping获取handler的整体流程,分析了RequestMappingHandlerMapping及其父类之间的关系。
getHandler主要干下面三件事情:
在开始看代码之前先了解一下HandlerExecutionChain是个什么东西
public class HandlerExecutionChain {
private final Object handler;
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
}
其实就是handler+HandlerInterceptor列表
那handler又是什么东西?注意到它的类型是Object,在RequestMappingHandlerMapping中它就是HandlerMethod。
public class HandlerMethod {
private final Object bean;
@Nullable
private final BeanFactory beanFactory;
private final Class<?> beanType;
private final Method method;
private final Method bridgedMethod;
private final MethodParameter[] parameters;
@Nullable
private HttpStatus responseStatus;
@Nullable
private String responseStatusReason;
@Nullable
private HandlerMethod resolvedFromHandlerMethod;
}
HandlerMethod包含了处理 的方法的各种信息。
先看一下继承关系
AbstractHandlerMapping主要实现找handlerInterceptor,子类实现找handler。
我们先从AbstractHandlerMapping开始分析。
先看最重要的方法getHandler,这是dispatcherServlet调用HandlerMapping的入口。
// AbstractHandlerMapping
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 子类实现
Object handler = getHandlerInternal(request);
// hander相关的一些判断操作
// 当前类实现,获得handlerInterceptor,组合成HandlerExecutionChain
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
// cors相关
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = getCorsConfiguration(handler, request);
if (getCorsConfigurationSource() != null) {
CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
config = (globalConfig != null ? globalConfig.combine(config) : config);
}
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
getHandlerInternal是子类实现的,这个之后再看,先分析getHandlerExecutionChain。
// AbstractHandlerMapping
// HandlerInterceptor列表
private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
// 处理MappedInterceptor
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(request)) {
//把Interceptor加到HandlerExecutionChain里面
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
// 处理普通Interceptor
chain.addInterceptor(interceptor);
}
}
return chain;
}
逻辑很简单,遍历this.adaptedInterceptors,把里面符合当前request的加到HandlerExecutionChain就好了。
唯一的问题就是这个this.adaptedInterceptors是怎么来的?
答案就在initApplicationContext这个方法里,AbstractHandlerMapping继承了ApplicationObjectSupport,而 ApplicationObjectSupport实现了ApplicationContextAware,所以initApplicationContext这个方法会在bean初始化的时候被调用。
// AbstractHandlerMapping
protected void initApplicationContext() throws BeansException {
// 空方法
extendInterceptors(this.interceptors);
// 找所有的MappedInterceptors,放到this.adaptedInterceptors里面
detectMappedInterceptors(this.adaptedInterceptors);
// 初始化Interceptors
initInterceptors();
}
// 就是按类查找
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}
// 把interceptors列表中的interceptor做个类型转换,然后放到adaptedInterceptors列表中
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
for (int i = 0; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
if (interceptor == null) {
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
上面找的是所有的MappedInterceptor,它和普通的Interceptor的关系是什么?
从xml配置文件看,它们的关系就是 < mvc:interceptor > 整体 和 MyInterceptor 的关系
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/abc/**" />
<mvc:exclude-mapping path="/xyz//*" />
<bean class="com.a.b.c.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
从代码中可以发现MappedInterceptor里面有具体的interceptor还有一些匹配路径相关的东西。
public final class MappedInterceptor implements HandlerInterceptor {
private static PathMatcher defaultPathMatcher = new AntPathMatcher();
@Nullable
private final PathPattern[] includePatterns;
@Nullable
private final PathPattern[] excludePatterns;
private PathMatcher pathMatcher = defaultPathMatcher;
private final HandlerInterceptor interceptor;
}
AbstractHandlerMapping就分析完了,接下去看AbstractHandlerMethodMapping
从AbstractHandlerMapping留给子类的getHandlerInternal开始分析
// AbstractHandlerMethodMapping
// 存储mapping和HandlerMethod的映射,mapping包含了匹配某个handler method需要的条件。
// 通俗的说mapping就是用来描述@RequestMapping里面的各种条件
private final MappingRegistry mappingRegistry = new MappingRegistry();
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 从request获取路径
String lookupPath = initLookupPath(request);
// mappingRegistry上锁
this.mappingRegistry.acquireReadLock();
try {
// 从mappingRegistry里面找到handlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
接下来先来认识一下MappingRegistry。
T就表示mapping的类型,具体是RequestMappingInfo,在其子类RequestMappingInfoHandlerMapping中定义。
class MappingRegistry {
// 通过@RequestMapping里面的条件,得到各种映射信息,具体初始化位置见MappingRegistry初始化
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 根据url找所有的mapping
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
// 遍历根据url找到的所有的mapping,找和当前request匹配的,存到matches里面
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
// 处理匹配到好几个的情况
if (matches.size() > 1) {
// 比较器留给子类实现
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
bestMatch = matches.get(0);
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
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();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
// 有没有好奇过template uri里面的变量是怎么被传到入参里的
// 里面会把template uri(比如hi/{id})中的值解析,以map的形式存到request里面,之后在绑定入参时就可以用了
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
} else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
// 留给子类实现
T match = getMatchingMapping(mapping, request);
if (match != null) {
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
// AbstractHandlerMethodMapping
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
// 获得所有的beanName
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
// 找所有的handler method方法,如果有代理就找到代理方法,注册到mappingRegistry里面。
processCandidateBean(beanName);
}
}
// 没有逻辑代码,就log一下
handlerMethodsInitialized(getHandlerMethods());
}
继承AbstractHandlerMethodMapping,传入了具体的mapping类型:RequestMappingInfo。
public final class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
private final String name;
@Nullable
private final PathPatternsRequestCondition pathPatternsCondition;
@Nullable
private final PatternsRequestCondition patternsCondition;
private final RequestMethodsRequestCondition methodsCondition;
private final ParamsRequestCondition paramsCondition;
private final HeadersRequestCondition headersCondition;
private final ConsumesRequestCondition consumesCondition;
private final ProducesRequestCondition producesCondition;
private final RequestConditionHolder customConditionHolder;
private final int hashCode;
}
从父类AbstractHandlerMethodMapping留的getMatchingMapping和getMappingComparator方法开始分析。
// RequestMappingInfoHandlerMapping
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
return info.getMatchingCondition(request);
}
// RequestMappingInfo
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
if (methods == null) {
return null;
}
ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
if (params == null) {
return null;
}
HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
if (headers == null) {
return null;
}
ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
if (consumes == null) {
return null;
}
ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
if (produces == null) {
return null;
}
PathPatternsRequestCondition pathPatterns = null;
if (this.pathPatternsCondition != null) {
pathPatterns = this.pathPatternsCondition.getMatchingCondition(request);
if (pathPatterns == null) {
return null;
}
}
PatternsRequestCondition patterns = null;
if (this.patternsCondition != null) {
patterns = this.patternsCondition.getMatchingCondition(request);
if (patterns == null) {
return null;
}
}
RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
if (custom == null) {
return null;
}
return new RequestMappingInfo(
this.name, pathPatterns, patterns, methods, params, headers, consumes, produces, custom);
}
上述代码就是从request中找到符合当前RequestMappingInfo的条件,然后根据这些条件重新创建一个RequestMappingInfo。
// RequestMappingInfoHandlerMapping
protected Comparator<RequestMappingInfo> getMappingComparator(final HttpServletRequest request) {
return (info1, info2) -> info1.compareTo(info2, request);
}
// RequestMappingInfo
public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
int result;
// Automatic vs explicit HTTP HEAD mapping
if (HttpMethod.HEAD.matches(request.getMethod())) {
result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
if (result != 0) {
return result;
}
}
result = getActivePatternsCondition().compareTo(other.getActivePatternsCondition(), request);
if (result != 0) {
return result;
}
result = this.paramsCondition.compareTo(other.getParamsCondition(), request);
if (result != 0) {
return result;
}
result = this.headersCondition.compareTo(other.getHeadersCondition(), request);
if (result != 0) {
return result;
}
result = this.consumesCondition.compareTo(other.getConsumesCondition(), request);
if (result != 0) {
return result;
}
result = this.producesCondition.compareTo(other.getProducesCondition(), request);
if (result != 0) {
return result;
}
// Implicit (no method) vs explicit HTTP method mappings
result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
if (result != 0) {
return result;
}
result = this.customConditionHolder.compareTo(other.customConditionHolder, request);
if (result != 0) {
return result;
}
return 0;
}
就是按照不同条件的优先级,进行比较。
在AbstractHandlerMethodMapping初始化过程中,调用了的processCandidateBean方法,其中用到的两个两个方法都是留给子类去实现的。
// AbstractHandlerMethodMapping
protected abstract boolean isHandler(Class<?> beanType);
@Nullable
protected abstract T getMappingForMethod(Method method, Class<?> handlerType);
// RequestMappingHandlerMapping
protected boolean isHandler(Class<?> beanType) {
// 检查类上有没有Controller或者RequestMapping注解
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
// 获取方法上的信息
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
// 获取类上的信息,合并
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
下面斜体部分表示具体功能由子类实现。
这个类是获得method形式的handler的类,主要是有两部分,都是围绕MappingRegistry。MappingRegistry中mapping的具体类型是RequestMappingInfoHandlerMapping定义的。
初始化MappingRegistry
找到handler方法
获取handler方法的mapping,注册到MappingRegistry里面。
这两部分的具体实现会涉及到RequestMappingHandlerMapping。
通过MappingRegistry获得handler