springMVC源码简读——2.2 HandlerMapping的解析器(上)

整理完之后发现放在一章太长了,于是截断了。上:主要是介绍HandlerMapping 接口、抽象实现类、以及基于URL实现业务的HandlerMapping

概述

顶级接口

处理器匹配接口,根据请求( handler )获得其的处理器( handler )和拦截器们( HandlerInterceptor 数组 )
其顶级接口是

 public interface HandlerMapping {

	String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";

	String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";

	String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";

	String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";

	String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";

	String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";

	String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

	/**
	 * 获得请求对应的处理器和拦截器们
	 */
	@Nullable
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}

类图

接口HandlerMapping的类图关系

在这里插入图片描述

实现类

AbstractHandlerMapping

继承 WebApplicationObjectSupport 抽象类,HandlerMapping抽象基类,实现了【获得请求对应的处理器和拦截器们】的骨架逻辑

构造方法
// AbstractHandlerMapping.java

	/**
	 * 默认处理器
	 */
	@Nullable
	private Object defaultHandler;

	/**
	 *  URL 路径工具类
	 */
	private UrlPathHelper urlPathHelper = new UrlPathHelper();

	/**
	 * 路径匹配器
	 */
	private PathMatcher pathMatcher = new AntPathMatcher();
		/**
	 * 配置的拦截器数组.
	 *
	 * 添加方式有两种:
	 *
	 * 1. {@link #setInterceptors(Object...)} 方法
	 * 2. {@link #extendInterceptors(List)} 方法
	 */
	private final List<Object> interceptors = new ArrayList<>();
	
	/**
	 * 初始化后的拦截器 HandlerInterceptor 数组
	 */
	private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();
	
	/**
	 * 顺序,最低优先级
	 */
	private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

	/**
	 *  Bean 名字
	 */
	@Nullable
	private String beanName;
initApplicationContext

初始化拦截器

// AbstractHandlerMapping.java
@Override
	protected void initApplicationContext() throws BeansException {
		// 空方法。交给子类实现,用于注册自定义的拦截器到 interceptors 中。目前暂无子类实现。
		extendInterceptors(this.interceptors);
		// 扫描已注册的 MappedInterceptor 的 Bean 们,添加到 mappedInterceptors 中
		detectMappedInterceptors(this.adaptedInterceptors);
		// 将 interceptors 初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors 中
		initInterceptors();
	}
	
	// 扫描所有已经注册到容器中的MappedInterceptor类
	protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
		// 扫描已注册的 MappedInterceptor 的 Bean 们,添加到 mappedInterceptors 中
		// MappedInterceptor 会根据请求路径做匹配,是否进行拦截。
		mappedInterceptors.addAll(
				BeanFactoryUtils.beansOfTypeIncludingAncestors(
						obtainApplicationContext(), MappedInterceptor.class, true, false).values());
	}
	
	
initInterceptors

将 interceptors 初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors 中

protected void initInterceptors() {
		if (!this.interceptors.isEmpty()) {
			// 遍历 interceptors 数组
			for (int i = 0; i < this.interceptors.size(); i++) {
				// 获得 interceptor 对象
				Object interceptor = this.interceptors.get(i);
				if (interceptor == null) {
					throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
				}
				// 将 interceptors 初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors 中
				// 注意,HandlerInterceptor 无需进行路径匹配,直接拦截全部
				this.adaptedInterceptors.add(adaptInterceptor(interceptor));
			}
		}
	}
	
protected HandlerInterceptor adaptInterceptor(Object interceptor) {
		// HandlerInterceptor 类型,直接返回
		if (interceptor instanceof HandlerInterceptor) {
			return (HandlerInterceptor) interceptor;
		}
		// WebRequestInterceptor 类型,适配成 WebRequestHandlerInterceptorAdapter 对象,然后返回
		else if (interceptor instanceof WebRequestInterceptor) {
			return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
		}
		// 错误类型,抛出 IllegalArgumentException 异常
		else {
			throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
		}
	}	
	
getHandler

获得请求对应的hand执行链,这个请求在3.1中介绍请求过程的代码中会调用到,是handlerMapping 的核心之一

// AbstractHandlerMapping.java

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 获得处理器。该方法是抽象方法,由子类实现
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			// 获得不到,则使用默认处理器
			handler = getDefaultHandler();
		}
		// 还是获得不到,则返回 null
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		// <4> 如果找到的处理器是 String 类型,则从容器中找到 String 对应的 Bean 类型作为处理器。
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			// 从上下文中获得handler
			handler = obtainApplicationContext().getBean(handlerName);
		}

		// 获得 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 (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;
	}
	

getHandlerInternal是获得handler的方法,基类不实现,子类实现。

getHandlerExecutionChain

获得处理器执行链

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		// 创建 HandlerExecutionChain 对象
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		// 获得请求路径
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		// 遍历 adaptedInterceptors 数组,获得请求匹配的拦截器
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			// 需要匹配,若路径匹配,则添加到 chain 中
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			// 无需匹配,直接添加到 chain 中
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

MatchableHandlerMapping

基于HandlerMapping 接口的扩展。定义判断请求和指定 pattern 路径是否匹配的接口方法

public interface MatchableHandlerMapping extends HandlerMapping {

	/**
	 * 判断请求和指定 `pattern` 路径是否匹配的接口方法
	 */
	@Nullable
	RequestMatchResult match(HttpServletRequest request, String pattern);

}

RequestMatchResult

匹配结果的封装对象,包含了匹配值,被匹配值,和匹配器参数

public class RequestMatchResult {

	/**
	 * 匹配上的路径
	 */
	private final String matchingPattern;

	/**
	 * 被匹配的路径
	 */
	private final String lookupPath;

	/**
	 * 路径匹配器
	 */
	private final PathMatcher pathMatcher;


	public RequestMatchResult(String matchingPattern, String lookupPath, PathMatcher pathMatcher) {
		Assert.hasText(matchingPattern, "'matchingPattern' is required");
		Assert.hasText(lookupPath, "'lookupPath' is required");
		Assert.notNull(pathMatcher, "'pathMatcher' is required");
		this.matchingPattern = matchingPattern;
		this.lookupPath = lookupPath;
		this.pathMatcher = pathMatcher;
	}


	public Map<String, String> extractUriTemplateVariables() {
		return this.pathMatcher.extractUriTemplateVariables(this.matchingPattern, this.lookupPath);
	}

}

初始化

初始化的地方还是在DispatcherServlet没得说,方法是initHandlerMappings,一样的套路,优先判断扫描,然后从容器中获取,假如都没有则使用默认值

	private void initHandlerMappings(ApplicationContext context) {
		// 置空 handlerMappings
		this.handlerMappings = null;

		// 如果开启探测功能,则扫描已注册的 HandlerMapping 的 Bean 们,添加到 handlerMappings 中
		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			// 扫描已注册的 HandlerMapping 的 Bean 们
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			// 添加到 handlerMappings 中,并进行排序
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		// 如果关闭探测功能,则获得 HANDLER_MAPPING_BEAN_NAME 对应的 Bean 对象,并设置为 handlerMappings
		else {
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		// 如果未获得到,则获得默认配置的 HandlerMapping 类
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}


实现类-基于 URL 进行匹配

AbstractUrlHandlerMapping

以 URL 作为 Handler 的 HandlerMapping 抽象类,提供 Handler 的获取
注意是org.springframework.web.servlet.handler下的

构造函数
// AbstractUrlHandlerMapping.java
    /**
	 * 处理器
	 */
	@Nullable
	private Object rootHandler;
	/**
	 * 使用后置匹配
	 */
	private boolean useTrailingSlashMatch = false;
	/**
	 * 是否延迟加载
	 */
	private boolean lazyInitHandlers = false;
	/**
	 * 路径和处理器映射
	 */
	private final Map<String, Object> handlerMap = new LinkedHashMap<>();
registerHandler

注册多个URL的处理器

// AbstractUrlHandlerMapping.java

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);
		}
	}
	
	
		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;

		// Eagerly resolve handler if referencing singleton via name.
		// 如果非延迟加载,并且 handler 为 String 类型
		if (!this.lazyInitHandlers && handler instanceof String) {
			String handlerName = (String) handler;
			ApplicationContext applicationContext = obtainApplicationContext();
			// 如果是单例的就去容器中获得处理器
			if (applicationContext.isSingleton(handlerName)) {
				resolvedHandler = applicationContext.getBean(handlerName);
			}
		}
		// 从已经加载的映射集合中获取url对应的处理器
		Object mappedHandler = this.handlerMap.get(urlPath);
		// 如果已经存在,并且和 resolvedHandler 不同,代表一个url映射了两个处理器,
		// 则抛出 IllegalStateException 异常
		if (mappedHandler != null) {
			if (mappedHandler != resolvedHandler) {
				throw new IllegalStateException(
						"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
						"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
			}
		}
		else {
			// 如果是根路径则设置根处理器RootHandler
			if (urlPath.equals("/")) {
				if (logger.isTraceEnabled()) {
					logger.trace("Root mapping to " + getHandlerDescription(handler));
				}
				setRootHandler(resolvedHandler);
			}
			// 如果是/*则设置默认处理器
			else if (urlPath.equals("/*")) {
				if (logger.isTraceEnabled()) {
					logger.trace("Default mapping to " + getHandlerDescription(handler));
				}
				setDefaultHandler(resolvedHandler);
			}
			// 将路径映射添加到集合中
			else {
				this.handlerMap.put(urlPath, resolvedHandler);
				if (logger.isTraceEnabled()) {
					logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler));
				}
			}
		}
	}
	

在下面的实现可以发现,整个路径处理器的注册就是根据路径和bean名称,先通过bean名称获得bean然后将映射添加到映射集合中。

getHandlerInternal

获得处理器,根据路径去上面的集合中获得,路径匹配的处理器

// AbstractUrlHandlerMapping.java
	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
		// 获得请求路径
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		// 通过路径去集合中获得处理器
		Object handler = lookupHandler(lookupPath, request);
		// 如果处理器为空
		if (handler == null) {
			// We need to care for the default handler directly, since we need to
			// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
			Object rawHandler = null;
			// 假如是根路径获得根处理器
			if ("/".equals(lookupPath)) {
				rawHandler = getRootHandler();
			}
			// 还是空,则取默认处理器
			if (rawHandler == null) {
				rawHandler = getDefaultHandler();
			}
			// 假如还是没有定位到,这判断是否字符串
			// 假如是就去容器中拿
			if (rawHandler != null) {
				// Bean name or resolved handler?
				if (rawHandler instanceof String) {
					String handlerName = (String) rawHandler;
					rawHandler = obtainApplicationContext().getBean(handlerName);
				}
				validateHandler(rawHandler, request);
				// 创建处理器
				handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
			}
		}
		return handler;
	}

lookupHandler

获得处理器

// AbstractUrlHandlerMapping.java
	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
		// Direct match?
		// 直接在集合中获得处理器
		Object handler = this.handlerMap.get(urlPath);
		if (handler != null) {
			// Bean name or resolved handler?
			// 如果找到的处理器是 String 类型,则从容器中找到 String 对应的 Bean 类型作为处理器。
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			return buildPathExposingHandler(handler, urlPath, urlPath, null);
		}

		// Pattern match?
		// Pattern 正则匹配合适的,并添加到 matchingPatterns 中
		List<String> matchingPatterns = new ArrayList<>();
		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()) {
			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 + "]");
				}
			}
			// Bean name or resolved handler?
			// 如果找到的处理器是 String 类型,则从容器中找到 String 对应的 Bean 类型作为处理器。
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);

			// There might be multiple 'best patterns', let's make sure we have the correct URI template variables
			// for all of them
			// 获得路径参数集合
			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);
		}

		// No handler found...
		return null;
	}
buildPathExposingHandler

主要给处理器注册两个拦截器PathExposingHandlerInterceptor,UriTemplateVariablesHandlerInterceptor;当前url实际匹配的Pattern、匹配条件和url模板参数设置到request的属性

// AbstractUrlHandlerMapping.java
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
			String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {
		// 创建 HandlerExecutionChain 对象
		HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
		// 将路径和映射拼装成拦截器,添加HandlerExecutionChain中
		chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
		// 添加 UriTemplateVariablesHandlerInterceptor 拦截器,到 chain 中
		if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
			chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
		}
		return chain;
	}
match

执行匹配

// AbstractUrlHandlerMapping.java
	public RequestMatchResult match(HttpServletRequest request, String pattern) {
		// 获得请求路径
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		// 假如匹配返回【匹配对象
		if (getPathMatcher().match(pattern, lookupPath)) {
			return new RequestMatchResult(pattern, lookupPath, getPathMatcher());
		}
		else if (useTrailingSlashMatch()) {
			if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) {
				return new RequestMatchResult(pattern + "/", lookupPath, getPathMatcher());
			}
		}
		// 否则返回null
		return null;
	}

为handler注册的两个拦截器
  • PathExposingHandlerInterceptor

设置url路径匹配数据

	private class PathExposingHandlerInterceptor extends HandlerInterceptorAdapter {

		/**
		 * 最佳路径
		 */
		private final String bestMatchingPattern;
		/**
		 * 被匹配的路径
		 */
		private final String pathWithinMapping;

		public PathExposingHandlerInterceptor(String bestMatchingPattern, String pathWithinMapping) {
			this.bestMatchingPattern = bestMatchingPattern;
			this.pathWithinMapping = pathWithinMapping;
		}

		@Override
		public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
			// 将最佳路径和被匹配路径设置到request中
			exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request);
			// 将handler设置到request
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, handler);
			// 否支持类型级别映射
			request.setAttribute(INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings());
			return true;
		}

	}
  • UriTemplateVariablesHandlerInterceptor

设置url模板参数

	private class UriTemplateVariablesHandlerInterceptor extends HandlerInterceptorAdapter {

		/**
		 * url 模板参数
		 */
		private final Map<String, String> uriTemplateVariables;

		public UriTemplateVariablesHandlerInterceptor(Map<String, String> uriTemplateVariables) {
			this.uriTemplateVariables = uriTemplateVariables;
		}

		@Override
		public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
			// 将模板参数设置到request中
			exposeUriTemplateVariables(this.uriTemplateVariables, request);
			return true;
		}
	}

SimpleUrlHandlerMapping

继承 AbstractUrlHandlerMapping 抽象类,UrlHandlerMapping 实现类

构造函数
// SimpleUrlHandlerMapping.java

	/**
	 * url 和 处理器的映射
	 */
	private final Map<String, Object> urlMap = new LinkedHashMap<>();
	
initApplicationContext

进行初始化

// SimpleUrlHandlerMapping.java
public void initApplicationContext() throws BeansException {
		super.initApplicationContext();
		// 初始化路径的映射关系
		registerHandlers(this.urlMap);
	}

AbstractDetectingUrlHandlerMapping

继承 AbstractUrlHandlerMapping 抽象类,自动探测的 UrlHandlerMapping 抽象实现类

initApplicationContext

进行初始化,调用父类进行初始化,但是他注册映射关系使用的是

// AbstractDetectingUrlHandlerMapping.java
public void initApplicationContext() throws ApplicationContextException {
		super.initApplicationContext();
		// 自动探测
		detectHandlers();
	}
	
	protected void detectHandlers() throws BeansException {
		// 从容器中获得类名
		ApplicationContext applicationContext = obtainApplicationContext();
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		// Take any bean name that we can determine URLs for.
		// 遍历 Bean ,逐个注册
		for (String beanName : beanNames) {
			// 根据类名获得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());
		}
	}
	

然而determineUrlsForHandler并没有实现,所以需要看他的子类

BeanNameUrlHandlerMapping

基于 Bean 的名字来自动探测的 HandlerMapping 实现类

// BeanNameUrlHandlerMapping.java
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {

	/**
	 * Checks name and aliases of the given bean for URLs, starting with "/".
	 */
	@Override
	protected String[] determineUrlsForHandler(String beanName) {
		List<String> urls = new ArrayList<>();
		// 如果是以 / 开头,添加到 urls
		if (beanName.startsWith("/")) {
			urls.add(beanName);
		}
		// 获得bean的别名假如以/开头则添加到urls中
		String[] aliases = obtainApplicationContext().getAliases(beanName);
		for (String alias : aliases) {
			if (alias.startsWith("/")) {
				urls.add(alias);
			}
		}
		return StringUtils.toStringArray(urls);
	}

}

这个…………我还没想明白是什么场景使用的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值