系列传送门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方法执行。