AbstractUrlHandlerMapping类详解 - HandlerMapping系列二

AbstractUrlHandlerMapping是AbstractHandlerMapping的子类,实现针对beanName注册为handler对象。

registerHandler() 注册handler对象

//注册url和Bean的map,注册多个string的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和Bean的map,将具体的Handler注入到url对应的map中  
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类型而且没有设置lazyInitHandlers则从springMVC容器中获取handler  
	if (!this.lazyInitHandlers && handler instanceof String) {  
		String handlerName = (String) handler;  
		if (getApplicationContext().isSingleton(handlerName)) {  
			resolvedHandler = getApplicationContext().getBean(handlerName);  
		}  
	}  
	//是否已存在对应的handler
	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.");  
		}  
	}  
	else {  
		//未存在
		if (urlPath.equals("/")) {  
			if (logger.isInfoEnabled()) {  
				logger.info("Root mapping to " + getHandlerDescription(handler));  
			}  
			//"/"-->设置为roothandler
			setRootHandler(resolvedHandler);  
		}  
		else if (urlPath.equals("/*")) {  
			if (logger.isInfoEnabled()) {  
				logger.info("Default mapping to " + getHandlerDescription(handler));  
			}  
			//对"/*"的匹配设置默认的handler
			setDefaultHandler(resolvedHandler);  
		}  
		else {  
			//其余的路径绑定关系则存入handlerMap
			this.handlerMap.put(urlPath, resolvedHandler);  
			if (logger.isInfoEnabled()) {  
				logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));  
			}  
		}  
	}  
}  

在注册handler的时候可以多路径绑定一个bean,也可以通过请求路径绑定bean。

getHandlerInternal() 获取Handler

@Override
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
	 // 根据request获取url
	 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
	 // 根据url查找handler
	 Object handler = lookupHandler(lookupPath, request);
	 if (handler == null) {
		 // 如果没有匹配到handler需要查找默认的,下面需要将PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE缓存到request
		 // 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 = getApplicationContext().getBean(handlerName);
			 }
			 // 预留的校验handler模板方法,没有使用
			 validateHandler(rawHandler, request);
			 // 添加expose属性到request的拦截器
			 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;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
	 // Direct match? 直接根据url进行查找handler
	 Object handler = this.handlerMap.get(urlPath);
	 if (handler != null) {
		 // Bean name or resolved handler?
		 if (handler instanceof String) {
			 String handlerName = (String) handler;
			 handler = getApplicationContext().getBean(handlerName);
		 }
		 validateHandler(handler, request);
		 return buildPathExposingHandler(handler, urlPath, urlPath, null);
	 }
	 // Pattern match? 通过表达式进行匹配具体通过AntPathMatcher实现,具体后面分析
	 ListmatchingPatterns = new ArrayList();
	 for (String registeredPattern : this.handlerMap.keySet()) {
		 if (getPathMatcher().match(registeredPattern, urlPath)) {
			 matchingPatterns.add(registeredPattern);
		 }
	 }
	 String bestPatternMatch = null;
	 //匹配规则  
	 ComparatorpatternComparator = getPathMatcher().getPatternComparator(urlPath);
	 if (!matchingPatterns.isEmpty()) {
		 Collections.sort(matchingPatterns, patternComparator);
		 if (logger.isDebugEnabled()) {
		   logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
		 }
		 // order序号最小的优先级最高
		 bestPatternMatch = matchingPatterns.get(0);
	 }
	 if (bestPatternMatch != null) {
		 handler = this.handlerMap.get(bestPatternMatch);
		 // Bean name or resolved handler?
		 if (handler instanceof String) {
			 String handlerName = (String) handler;
			 handler = getApplicationContext().getBean(handlerName);
		 }
		 validateHandler(handler, request);
		 String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);

		 // There might be multiple 'best patterns', let's make sure we have the correct URI template variables
		 // for all of them
		 Map uriTemplateVariables = new LinkedHashMap();
		 for (String matchingPattern : matchingPatterns) {
			 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
			   Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
				 Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
				 uriTemplateVariables.putAll(decodedVars);
			 }
		 }
		 if (logger.isDebugEnabled()) {
			 logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
		 }
		 return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
	 }
	 // No handler found...
	 return null;
 }
//用于给找到的Handler注册两个拦截器PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor  
//这两个拦截器的的作用是将与当前url实际匹配的Pattern、匹配条件和url模板参数设置到request的属性中  
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,  
		String pathWithinMapping, Map uriTemplateVariables) {  

	HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);  
	chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));  
	if (!CollectionUtils.isEmpty(uriTemplateVariables)) {  
		chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));  
	}  
	return chain;  
}

getHandlerInternal首先是通过lookupHandler方法来查找Handler,这里我们看到了之前说的Map对象,用来存储url和Handler之间的关系,当Handler获取为String时需要从Bean容器中获取注入的实现类,当然在查找过程中也会有模糊匹配等查找过程。  

总结

AbstractUrlHandlerMapping主要是将请求路径绑定beanName,它提供的功能是根据url从handlerMap中获取handler和注册url和handler的对应关系到handlerMap中。

版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。