系列传送门Spring MVC源码和设计思想1 DispatcherServlet-鱼鱼的博客
综述
此篇篇幅很长,且慢慢道来。
在之前一篇中,DispatchServlet的doDispatch()方法中有这么几行:
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
其中getHandler方法:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
handlerMappings是一个初始化过的List<HandlerMapping>,通过它获取HandlerExecutionChain。HandlerExecutionChain存储了一个Object(其实就是HandleAdapter)和一个拦截器(HandlerInterceptor)数组,在doDispatch方法中执行了applyPreHandle和applyPostHandle方法,方法就是分别迭代调用了拦截器数组的postHandle和preHandle,同样地,发生异常时的triggerAfterCompletion也映射到了afterCompletion方法。
HanddlerMapping是非常简单的接口,只定义了一个getHandler方法,通过request选择对应的Handler。
HanddlerMapping的基本实现是抽象类AbstractHandlerMapping。相关类图:

AbstractHandlerMapping
继承了HandlerMapping的方法如下:
// AbstractHandlerMapping.java
@Override
@Nullable
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?
// String的Handler
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// 1 获得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 (hasCorsConfigurationSource(handler)) {
CorsConfiguration config = (this.corsConfigurationSource != null ?
this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
继承他的类主要便是依靠重写getHandlerInternal方法实现对应的功能。
1处的方法代码:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//获取请求路径
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
//遍历拦截器数组,匹配添加
相应的拦截器
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;
}
AbstractHandlerMethodMapping
首先看最关键的方法重写,会返回HandlerMethod方法
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获得请求路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
//获得写锁
this.mappingRegistry.acquireReadLock();
try {
//1
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
//释放锁
this.mappingRegistry.releaseReadLock();
}
}
lookupHandlerMethod()
1处调用了这一方法,
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
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...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
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);
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
在解释之前,我们需要看MappingRegistry中的相应方法。
MappingRegistry
MappingRegistry是AbstractHandlerMethodMapping的私有类,主要负责Mapping的注册。其中在上文中调用的锁处理在这里就略过,其实就是一个ReentrantReadWriteLock对象。
下面过一下方法和变量:
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 createHandlerMethod(Object handler, Method method) {
if (handler instanceof String) {
return new HandlerMethod((String) handler,
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
}
return new HandlerMethod(handler, method);
}
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//校验mapping,需要为空才可以
validateMethodMapping(handlerMethod, mapping);
this.mappingLookup.put(mapping, handlerMethod);
//mapping-url对应
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
其中调用了createWithResolvedBean方法:
public HandlerMethod createWithResolvedBean() {
Object handler = this.bean;
if (this.bean instanceof String) {
Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
String beanName = (String) this.bean;
handler = this.beanFactory.getBean(beanName);
}
return new HandlerMethod(this, handler);
}
初始化内容 关键定义如下:
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
}
tip:InitializingBean接口
AbstractHandlerMethodMapping方法继承了InitizlizingBean接口,其唯一的方法afterPropertiesSet()将会在继承他的类bean被初始化的时候执行,并且先于init方法执行。

