springmvc第四篇 --HandlerMapping

HandlerMapping组件分析

HandlerMapping继承结构
在这里插入图片描述
可以看到AbstractHandlerMapping分为两只:一只继承AbstractUrlHandlerMapping,一只继承与AbstractHandlerMethodMapping。

AbstractHandlerMapping是handlerMapping的抽象实现。AbstractHandlerMapping采用模板方法模式HandlerMapping实现了整体架构,字类只需要通过模板方法提供一些初始值或具体的算法即可。获取handler的方法通过模板方法getHandlerInternal交给了字类。AbstractHandlerMapping中保存了所用配置的interceptors。

AbstractHandlerMapping继承了WebApplicationObjectSupport,初始化时会调用initApplicationContext方法。

AbstractHandlerMapping系列

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
		implements HandlerMapping, Ordered, BeanNameAware {

	//默认的handler
	@Nullable
	private Object defaultHandler;

	//url匹配工具类
	private UrlPathHelper urlPathHelper = new UrlPathHelper();

	//正则匹配对象
	private PathMatcher pathMatcher = new AntPathMatcher();
	
	private final List<Object> interceptors = new ArrayList<>();
	
	private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();

	private CorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();

	private CorsProcessor corsProcessor = new DefaultCorsProcessor();

	private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

	@Nullable
	private String beanName;
	
	protected void initApplicationContext() throws BeansException {
		//给子类提供一个修改或添加interceptors的方法
		extendInterceptors(this.interceptors);
		//将容器中所有类型的MappedInterceptor添加到adaptedInterceptors中
		detectMappedInterceptors(this.adaptedInterceptors);
		//初始化interceptors,将符合的interceptor转换成HandlerInterceptor类型,添加到adaptedInterceptors中
		initInterceptors();
	}
	
	//初始化Interceptor
	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));
			}
		}
	}
	
	//获取HandlerExecutionChain链对象
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//模板方法字类实现 获取handler
		Object handler = getHandlerInternal(request);
		//为空就获取默认的handler
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// 判断是否为字符串,是字符串通过beanNames从容器中获取对象
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}
		//获取拦截器链
		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);
		}
		return executionChain;
	}

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		//判断handler是不是HandlerExecutionChain 类型,不是则创建一个
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
		//获取请求路径
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		//遍历adaptedInterceptors,然后将MappedInterceptor进行匹配进行加入,其它类型则直接加入
		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;
	}
}

AbstractUrlHandlerMapping系列

AbstractUrlHandlerMapping从名字上面来可以看出他是通过url来进行匹配的,是将url和对应的handler保存在一个map中。在getHandlerInternal中使用handlerMap来进行handler获取。另外还定义了处理"/"的handler。

public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {
	
	//根路径处理handler
	@Nullable
	private Object rootHandler;

	private boolean useTrailingSlashMatch = false;
	
	//懒加载handler
	private boolean lazyInitHandlers = false;

	//url和handler映射
	private final Map<String, Object> handlerMap = new LinkedHashMap<>();
	
	//获取handler	
	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
		//获取url
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		//获取处理器
		Object handler = lookupHandler(lookupPath, request);
		if (handler == null) {
			Object rawHandler = null;
			//判断是否用根处理器
			if ("/".equals(lookupPath)) {
				rawHandler = getRootHandler();
			}
			//判断是否用默认处理器,在父类定义了
			if (rawHandler == null) {
				rawHandler = getDefaultHandler();
			}
			if (rawHandler != null) {
				//判断为字符串,从容器中获取
				if (rawHandler instanceof String) {
					String handlerName = (String) rawHandler;
					rawHandler = obtainApplicationContext().getBean(handlerName);
				}
				//模板方法,验证handler和request是否匹配
				validateHandler(rawHandler, request);
				handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
			}
		}
		return handler;
	}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
		//直接用字符串匹配 主要匹配是通过handlerMap 进行匹配,下面会讲到handlerMap的初始化过程
		Object handler = this.handlerMap.get(urlPath);
		if (handler != null) {
			//如果是string从容器中获取
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			//验证是否合法
			validateHandler(handler, request);
			//返回拦截器链
			return buildPathExposingHandler(handler, urlPath, urlPath, null);
		}

		
		List<String> matchingPatterns = new ArrayList<>();
		//通过正则匹配路径 比如 * 和url匹配
		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 +"/");
				}
			}
		}

		String bestMatch = null;
		Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
		if (!matchingPatterns.isEmpty()) {
			//查询的handler进行排序
			matchingPatterns.sort(patternComparator);
			if (logger.isTraceEnabled() && matchingPatterns.size() > 1) {
				logger.trace("Matching patterns " + matchingPatterns);
			}
			bestMatch = matchingPatterns.get(0);
		}
		if (bestMatch != null) {
			handler = this.handlerMap.get(bestMatch);
			if (handler == null) {
				if (bestMatch.endsWith("/")) {
					handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
				}
				if (handler == null) {
					throw new IllegalStateException(
							"Could not find handler for best pattern match [" + bestMatch + "]");
				}
			}
		
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);

			
			Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
			for (String matchingPattern : matchingPatterns) {
				if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
					Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
					Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
					uriTemplateVariables.putAll(decodedVars);
				}
			}
			if (logger.isTraceEnabled() && uriTemplateVariables.size() > 0) {
				logger.trace("URI variables " + uriTemplateVariables);
			}
			return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
		}

		// 找不到返回null
		return null;
	}
	//创建拦截器链
	protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
			String pathWithinMapping, @Nullable 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;
	}
	
	**下面讲解handlerMap的初始化,它通过registerHandler方法进行,不过和之前创建的不同是,这里的registerHandler方法是通过子类调用。这样不同的子类可以通过不同的方式注册handlerMap。**
//注册多个url到容器
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
		Assert.notNull(urlPaths, "URL path array must not be null");
		for (String urlPath : urlPaths) {
			registerHandler(urlPath, beanName);
		}
	}

	//注册一个url到容器
	protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
		Assert.notNull(urlPath, "URL path must not be null");
		Assert.notNull(handler, "Handler object must not be null");
		Object resolvedHandler = handler;

		//  没设置懒加载并且是string类型 ,则从从其获取bean.
		if (!this.lazyInitHandlers && handler instanceof String) {
			String handlerName = (String) handler;
			ApplicationContext applicationContext = obtainApplicationContext();
			if (applicationContext.isSingleton(handlerName)) {
				resolvedHandler = applicationContext.getBean(handlerName);
			}
		}

		Object mappedHandler = this.handlerMap.get(urlPath);
		//如果已存在并不相等则报错
		if (mappedHandler != null) {
			if (mappedHandler != resolvedHandler) {
				throw new IllegalStateException(
						"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
						"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
			}
		}
		//如果已存在并等于"/"设置到rootHadler
		else {
			if (urlPath.equals("/")) {
				if (logger.isTraceEnabled()) {
					logger.trace("Root mapping to " + getHandlerDescription(handler));
				}
				setRootHandler(resolvedHandler);
			}
			//如果已存在并等于"/*"设置到DefaultHandler
			else if (urlPath.equals("/*")) {
				if (logger.isTraceEnabled()) {
					logger.trace("Default mapping to " + getHandlerDescription(handler));
				}
				setDefaultHandler(resolvedHandler);
			}
			else {
			//没有找到则put进去
				this.handlerMap.put(urlPath, resolvedHandler);
				if (logger.isTraceEnabled()) {
					logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler));
				}
			}
		}
	}
}

SimpleUrlHandlerMapping系列

public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {

	private final Map<String, Object> urlMap = new LinkedHashMap<>();
` 	
	//调用父类初始化
	public void initApplicationContext() throws BeansException {
		super.initApplicationContext();
		registerHandlers(this.urlMap);
	}
	
	//注册handlerMap
	protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
		if (urlMap.isEmpty()) {
			logger.trace("No patterns in " + formatMappingName());
		}
		else {
			urlMap.forEach((url, handler) -> {
				// Prepend with slash if not already present.
				if (!url.startsWith("/")) {
					url = "/" + url;
				}
				if (handler instanceof String) {
					handler = ((String) handler).trim();
				}
				//调用父类注册
				registerHandler(url, handler);
			});
			if (logger.isDebugEnabled()) {
				List<String> patterns = new ArrayList<>();
				if (getRootHandler() != null) {
					patterns.add("/");
				}
				if (getDefaultHandler() != null) {
					patterns.add("/**");
				}
				patterns.addAll(getHandlerMap().keySet());
				logger.debug("Patterns " + patterns + " in " + formatMappingName());
			}
		}
	}
}

AbstractDetectingUrlHandlerMapping系列

public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {

	//也是重写父类的initApplicationContext方法
	public void initApplicationContext() throws ApplicationContextException {
		super.initApplicationContext();
		detectHandlers();
	}

	protected void detectHandlers() throws BeansException {
		ApplicationContext applicationContext = obtainApplicationContext();
		//获取所有的bean
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		for (String beanName : beanNames) {
			//对bean解析url,模板方法,子类实现
			String[] urls = determineUrlsForHandler(beanName);
			//能解析就注册到父类
			if (!ObjectUtils.isEmpty(urls)) {
				// URL paths found: Let's consider it a handler.
				registerHandler(urls, beanName);
			}
		}

		if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {
			logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
		}
	}
}

AbstractDetectingUrlHandlerMapping有一个子类:BeanNameUrlHandlerMapping:

public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
    public BeanNameUrlHandlerMapping() {
    }
    
	//对beanName进行解析
    protected String[] determineUrlsForHandler(String beanName) {
        List<String> urls = new ArrayList();
        //p判断是不是以”/“开头,是的话就当做url
        if (beanName.startsWith("/")) {
            urls.add(beanName);
        }

        String[] aliases = this.obtainApplicationContext().getAliases(beanName);
        String[] var4 = aliases;
        int var5 = aliases.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String alias = var4[var6];
            if (alias.startsWith("/")) {
                urls.add(alias);
            }
        }

        return StringUtils.toStringArray(urls);
    }
}

AbstractHandlerMethodMapping系列

从前面类图来看 AbstractHandlerMethodMapping系列有两个子类:RequestMappingInfoHandlerMapping和RequestMappingHandlerMapping,这三个类一次继承。AbstractHandlerMethodMapping系列是把Method当作handler使用,这也是我们现在用得最多的一种handler,我们经常用的@RequestMapping所注释的方法就是这种handler,他专门有一个类型HandlerMethod。

在AbstractHandlerMethodMapping类中有一个内部类(MappingRegistry),下面我们来看一下。


	//在AbstractHandlerMethodMapping类中维护了一个MappingRegistry对象的引用。。
	private final MappingRegistry mappingRegistry = new MappingRegistry();

	/**
	 *一个注册表,它维护处理程序方法的所有映射,公开方法
	 */
	class MappingRegistry {
	
		// 里面配置的是requestMapponig中的映射,key是RequestMappingInfo类型 ,value是MappingRegistration类型也是	AbstractHandlerMethodMapping的内部类,里面有默认配置
		看一下本人debug的数据截图可能更方便理解! 里面有我们写的requestMapping和默认配置的错误页面.。
		private final Map<T, MappingRegistration<T>> registry = new HashMap<>();

registry

		//里面保存着requestMappingInfo和HandlerMethod对象
		private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();

mappingLookup

		//里面是url和匹配的requestMappingInfo对象
		//里面保存着url和匹配条件,当然这里的url可以是pattern式的,也可以是通配符模式,当然这里的Map不是扑通的map,而是MultiValueMap,这种key可以对应多个值map,他的值其实是一个list对象
		private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();

urlLookup

		//nameLookup 保存的是name和HandlerMethod的对用关系,这里的value是一个list类型,name的生成规则是#+方法名 这个nameLookup在正常的匹配中并不会使用
		private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();

nameLookup

		private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
		
		//在getHandlerInternal方法会进行加锁
		private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

		
		public Map<T, HandlerMethod> getMappings() {
			return this.mappingLookup;
		}

		
		@Nullable
		public List<T> getMappingsByUrl(String urlPath) {
			return this.urlLookup.get(urlPath);
		}

		public List<HandlerMethod> getHandlerMethodsByMappingName(String mappingName) {
			return this.nameLookup.get(mappingName);
		}
		/**
		 * Return CORS configuration. Thread-safe for concurrent use.
		 */
		public CorsConfiguration getCorsConfiguration(HandlerMethod handlerMethod) {
			HandlerMethod original = handlerMethod.getResolvedFromHandlerMethod();
			return this.corsLookup.get(original != null ? original : handlerMethod);
		}
		/**
		 * Acquire the read lock when using getMappings and getMappingsByUrl.
		 */
		public void acquireReadLock() {
			this.readWriteLock.readLock().lock();
		}
		/**
		 * Release the read lock after using getMappings and getMappingsByUrl.
		 */
		public void releaseReadLock() {
			this.readWriteLock.readLock().unlock();
		}
		public void register(T mapping, Object handler, Method method) {
			this.readWriteLock.writeLock().lock();
			try {
				HandlerMethod handlerMethod = createHandlerMethod(handler, method);
				assertUniqueMethodMapping(handlerMethod, mapping);
				this.mappingLookup.put(mapping, handlerMethod);
				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();
			}
		}

		private List<String> getDirectUrls(T mapping) {
			List<String> urls = new ArrayList<>(1);
			for (String path : getMappingPathPatterns(mapping)) {
				if (!getPathMatcher().isPattern(path)) {
					urls.add(path);
				}
			}
			return urls;
		}
	}
private static class MappingRegistration<T> {

		//requestMapponigInfo对象
		private final T mapping;
		
		//HandlerMethod对象 
		private final HandlerMethod handlerMethod;

		//url路径,从request中获取
		private final List<String> directUrls;

		//解析规则是 #+方法名
		@Nullable
		private final String mappingName;
	}
	介绍一下urlLookup和mappingLookup,通过urlLookup找到符合的requestMappingInfo对象,在通过mappingLookup以查询出来的mappingLookup对象找寻对用的handlermethod对象。
	
	//从上面的代码看出,主要的解析工作都在于3个map,现在我们看一下map的初始化。
	AbstractHandlerMethodMapping实现了InitializingBean接口,所以容器会自动调用	afterPropertiesSet方法,afterPropertiesSet又交给initHandlerMethods进行初始化工作。
	
	public void afterPropertiesSet() {
		initHandlerMethods();
	}
	
	protected void initHandlerMethods() {
		
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				processCandidateBean(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

	//获取候选的bean
	protected String[] getCandidateBeanNames() {
		return (this.detectHandlerMethodsInAncestorContexts ?
		BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
				obtainApplicationContext().getBeanNamesForType(Object.class));
	}
	
		//通过beanName先获取beanType,不为空判断是不是handler,调用isHandler方法
	protected void processCandidateBean(String beanName) {
		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);
			}
		}
		if (beanType != null && isHandler(beanType)) {
			//注册beanName
			detectHandlerMethods(beanName);
		}
	}

	//判断bean前是否有Controller或RequestMapping注解
	protected boolean isHandler(Class<?> beanType) {
		return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
				AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
	}
	
	//detectHandlerMethods方法负责将handler保存到map中
	protected void detectHandlerMethods(Object handler) {
		//获取handler的class
		Class<?> handlerType = (handler instanceof String ?
				obtainApplicationContext().getType((String) handler) : handler.getClass());

		if (handlerType != null) {
			//如果是cglib代理子对象类型,则返回父类型,否则返回本身
			Class<?> userType = ClassUtils.getUserClass(handlerType);
			//获取当前bean中符合handler要求的method,
			//遍历传入userType的所有方法,通过匿名getMappingForMethod方法进行匹配
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});
			if (logger.isTraceEnabled()) {
				logger.trace(formatMappings(userType, methods));
			}
			methods.forEach((method, mapping) -> {
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
				//将符合要求的数据保存起来
				registerHandlerMethod(handler, invocableMethod, mapping);
			});
		}
		
	说完了找到的HandlerMethod,在看一下怎么注册进去的
	protected void registerHandlerMethod(Object handler, Method method, T mapping) {
		this.mappingRegistry.register(mapping, handler, method);
	}
	
	public void register(T mapping, Object handler, Method method) {
			this.readWriteLock.writeLock().lock();
			try {
				//创建HandlerMethod对象
				HandlerMethod handlerMethod = createHandlerMethod(handler, method);
				//验证
				assertUniqueMethodMapping(handlerMethod, mapping);
				//添加到mappingLookup中
				this.mappingLookup.put(mapping, handlerMethod);
				
				//添加到	urlLookup
				List<String> directUrls = getDirectUrls(mapping);
				for (String url : directUrls) {
					this.urlLookup.add(url, mapping);
				}

				String name = null;
				//添加到	nameLookup 调用addMappingName方法
				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);
				}
				//把映射封装到registry中
				this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
			}
			finally {
				this.readWriteLock.writeLock().unlock();
			}
		}

	private void assertUniqueMethodMapping(HandlerMethod newHandlerMethod, T mapping) {
			//验证handlerMethod 是否已存在,如果已存在和现在传入的不同则抛异常
			HandlerMethod handlerMethod = this.mappingLookup.get(mapping);
			if (handlerMethod != null && !handlerMethod.equals(newHandlerMethod)) {
				throw new IllegalStateException(
						"Ambiguous mapping. Cannot map '" +	newHandlerMethod.getBean() + "' method \n" +
						newHandlerMethod + "\nto " + mapping + ": There is already '" +
						handlerMethod.getBean() + "' bean method\n" + handlerMethod + " mapped.");
			}
		}
	
		//检查是否存在,存在并且相等直接返回,不相等的话放到新的List中put进去
	private void addMappingName(String name, HandlerMethod handlerMethod) {
			List<HandlerMethod> oldList = this.nameLookup.get(name);
			if (oldList == null) {
				oldList = Collections.emptyList();
			}
			for (HandlerMethod current : oldList) {
				if (handlerMethod.equals(current)) {
					return;
				}
			}
			List<HandlerMethod> newList = new ArrayList<>(oldList.size() + 1);
			newList.addAll(oldList);
			newList.add(handlerMethod);
			this.nameLookup.put(name, newList);
		}

通过前面的分析,这个类的主要功能是通过getHandlerInternal获取处理器,下面看一下代码:

rotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		//获取url
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		this.mappingRegistry.acquireReadLock();
		try {
				//调用方法返回handler
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}
	
	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<>();
		//这个代码很简单,从urlLookup获取handler
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
			//将找到的加入matches
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
				//如果为空的话 从mappingLookup获取所有的key添加到matches 
			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 + "}");
				}
			}
			//将handlerMethod放入request的BEST_MATCHING_HANDLER_ATTRIBUTE
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		}
		else {
			//如果没有handler 在此匹配所有,查看url是否匹配,不匹配则抛出异常
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

详细的过程已经做了注释,整个过程以Match作为载体,Match是个内部类,封装了匹配条件和HandlerMethod两个属性。子类RequestMappingInfoHandlerMapping中进行了重写,将更多参数设置到request的属性,主要为了以后使用时方便。
小结:此篇详细分析的HandlerMapping的各种实现方式,HandlerMapping在AbstractHandlerMapping中设计其功能是根据request找寻handler和interceptors,组合成handlerExecutionChain类型返回。找寻handler的handlerInternal方法由子类实现,找寻interceptors则由自己实现,具体由几个map实现。
AbstractHandlerMapping系列分为两个子类:AbstractHandlerMethodMapping和AbstractUrlHandlerMapping。前者匹配的内容比较多,而且直接匹配到method,后者通过url匹配,这也是使用对多的方式。
参考资料:看透springmvc源码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值