HandlerMapping接口只有一个方法app
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
就是根据Reuqest返回HandlerExecutionChain,看名字就知道是一个处理链,包含多个Interceptor和一个Handler。cors
AbstractHandlerMapping是HanlderMapping的默认实现类。是一个模板方法(Spring 底层大代码大量使用模板方法)。ide
@Override protected void initApplicationContext() throws BeansException { extendInterceptors(this.interceptors); detectMappedInterceptors(this.adaptedInterceptors); initInterceptors(); }
deleteMappedIntercptors方法的左右就是把ApplicationContext中全部类型为MappedInterceptor的bean加入到adaptedIntercptors这个成员变量中函数
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) { mappedInterceptors.addAll( BeanFactoryUtils.beansOfTypeIncludingAncestors( getApplicationContext(), MappedInterceptor.class, true, false).values()); }
initInterceptors()函数的做用就是把成员变量interceptors中的interceptor加入到adaptedInterceptors成员变量中去,若是是WebRequestInterceptor则转换为对应的adapter类,代码以下ui
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)); } } }
protected HandlerInterceptor adaptInterceptor(Object interceptor) { if (interceptor instanceof HandlerInterceptor) { return (HandlerInterceptor) interceptor; } else if (interceptor instanceof WebRequestInterceptor) { return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor); } else { throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName()); } }
@Override public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
主要作了2件事:this
AbstractHandleMapping是一个模板方法,子类须要实现getHandlerInternal。下面介绍2个主要实现类AbstractUrlHandleMapping和AbstractHandleMethodMapping。url
从名字能够猜到,AbstractUrlHandleMapping是经过url来匹配对应的Handler。AbstractUrlHandleMapping依然是一个抽象类。getHandlerInternal代码:spa
/** * 根据request的url查询对应的handler */ @Override protected Object getHandlerInternal(HttpServletRequest request) throws Exception { //查找url地址,有多是servlet的url,也有多是Spring Mvc定义的url String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); //经过url查找对应的Handler Object handler = lookupHandler(lookupPath, request); //若是找不到对应的handler if (handler == null) { // 特殊状况,若是查询地址为"/",则判断是否用rootHandler,若是没有就设置为defaultHandler Object rawHandler = null; if ("/".equals(lookupPath)) { rawHandler = getRootHandler(); } if (rawHandler == null) { rawHandler = getDefaultHandler(); } if (rawHandler != null) { // 若是是字符串,则从ApplicationConetxt中获取对应的bean if (rawHandler instanceof String) { String handlerName = (String) rawHandler; rawHandler = getApplicationContext().getBean(handlerName); } //模板方法,验证Handler validateHandler(rawHandler, request); //返回HandlerExecutionChain类型,会注册2个interceptor //PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor 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; }
主要作了一下几件事:debug
- 根据request生成查询handler的URL
- 根据url获取对应的handler
- 若是handler没有在map中查到,则使用默认的handler。
方法目的就是根据url 查找对应的Handler,可是在url匹配的时候每每会有"/test/*"或者Path变量“/test/{id}”这样的状况,这样就没法经过url地址直接从map中获取对应的handler。code
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { // 可否直接找到 Object handler = this.handlerMap.get(urlPath); if (handler != null) { // 若是是字符串从ApplicationContext中直接获取 if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } // 模板方法,验证handler validateHandler(handler, request); //返回HandlerExecutionChain类型,会注册2个interceptor //PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor return buildPathExposingHandler(handler, urlPath, urlPath, null); } // 模板匹配 List<String> matchingPatterns = new ArrayList<String>(); 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 +"/"); } } } //根据order找出优先级坐高的 String bestPatternMatch = 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); } bestPatternMatch = matchingPatterns.get(0); } if (bestPatternMatch != null) { handler = this.handlerMap.get(bestPatternMatch); if (handler == null) { Assert.isTrue(bestPatternMatch.endsWith("/")); handler = this.handlerMap.get(bestPatternMatch.substring(0, bestPatternMatch.length() - 1)); } if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } validateHandler(handler, request); String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); // 这里是处理当有多个url和最优的path是同一优先级的,那么从里面获取地址变量,加入到uriTemplateVariables中 Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>(); for (String matchingPattern : matchingPatterns) { if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars); uriTemplateVariables.putAll(decodedVars); } } return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); } //找不到对应的handler return null; }
这个函数主要完成了几下几件事
- url能直接从map中获取的则直接获取
- 不然经过路径pattern去匹配url
- 从全部匹配到handler查找出优先级最高的
- 若是有多个同最优先级的,则查看里面是否有pathVariable
- 找到任意的Handler则加入2个特殊的interceptor
上面全部的能成功找到对应的handler后,都会调用这个方法。这儿方法就是在handler的基础上,加入2个interceptor,返回一个HandlerExecutionChain
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern, String pathWithinMapping, Map<String, String> uriTemplateVariables) { HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler); chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping)); if (!CollectionUtils.isEmpty(uriTemplateVariables)) { chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables)); } return chain; }
这2个interceptor的做用就是当前匹配的url、匹配条件和url模板参数设置到request的attribute里面
上面一直说的经过url从map中获取对应的Handler,这个map是成员变量
private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
这个map的初始化是在registerHandler方法,这个方法比较功能比较简单,参数分别是url和handler,而后把url和handler放入map中,再作一些重复检查和特殊handler(roothandler)的设置。url和handler从哪里来,则又是子类提供处理具体的逻辑来调用这个方法。
到这里,关于怎么经过url来获取handler已经解决了,下面就是url和handler是怎么注册到handlermap中的,其中大部分子类都被@Deprecated标记,
这个类很是简单,就是给定参数map,注册到handlermap中
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException { if (urlMap.isEmpty()) { logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); } else { for (Map.Entry<String, Object> entry : urlMap.entrySet()) { String url = entry.getKey(); Object handler = entry.getValue(); // Prepend with slash if not already present. if (!url.startsWith("/")) { url = "/" + url; } // Remove whitespace from handler bean name. if (handler instanceof String) { handler = ((String) handler).trim(); } registerHandler(url, handler); } } }
如今来看看AbstractHandlerMapping的另一个继承 AbstractHandlerMethodMapping
AbstractHandlerMethodMapping从名字就能够看出,是把一个方法做为一个handler。而且继承体系也十分清晰。分析的顺序和AbstractUrlHandleMapping相似,首先仍是先分析一下getHandlerInternal这个方法
@Override 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(); } }
看起来和AbstractUrlHandleMapping相似,只不过AbstractUrlHandleMapping中的handler是一个bean,而AbstractHandlerMethodMapping的handler是一个Method
初始化方法initHandlerMethods:
protected void initHandlerMethods() { //获取全部beanName String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); for (String beanName : beanNames) { //beanName是以scopedTarget.开头的,则不用户Handler Method if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null; try { beanType = getApplicationContext().getType(beanName); } catch (Throwable ex) { ... } // isHandler模板方法,由子类去判断改bean是否注册 if (beanType != null && isHandler(beanType)) { //注册到HandlerMethod detectHandlerMethods(beanName); } } } //初始化HandlerMethod handlerMethodsInitialized(getHandlerMethods()); }
detectHandlerMethods,就是注册handlerMethod。具体说明看注解
protected void detectHandlerMethods(final Object handler) { Class<?> handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()); final Class<?> userType = ClassUtils.getUserClass(handlerType); //查找该handler中的method及其对应的条件(参照@RequestMapping中的参数) Map<Method, T> methods = MethodIntrospector.selectMethods(userType, new MethodIntrospector.MetadataLookup<T>() { @Override public T inspect(Method method) { return getMappingForMethod(method, userType); } }); for (Map.Entry<Method, T> entry : methods.entrySet()) { Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType); T mapping = entry.getValue(); registerHandlerMethod(handler, invocableMethod, mapping); } }
- isHandler 是一个模板方法,由子类去判断改bean是不是一个handler。
- getMappingForMethod也是一个模板方法,判断一个类中Method方法的相关条件信息
- detectHandlerMethods是在传入的beanName对应的bean中查找handlerMethod,而后注册
- handlerMethodsInitialized 是一个预留方法,里面没有作任何事,若是咱们自定义一个HandlerMapping有须要的话能够重写
RequestMappingHandlerMapping继承AbstractHandlerMethodMapping,首先看两个模板方法
isHandler,就是判断是否有Controller或者RequestMapping注解。
@Override protected boolean isHandler(Class<?> beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); }
getMappingForMethod这个方法就是根据传入的函数,返回一个RequestMappingInfo (也就是@RequestMapping中的参数信息)
@Override 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); } } return info; }
这样,AbstractHandlerMethodMapping的就能经过一个url能够找出对应MethodHandler,