【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

概括:

作用是根据request找到相应处理器Handler和Interceptors,HandlerMapping接口里只有一个方法:

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

我们也可以自己定义一个HandlerMapping,实现方法。

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

按顺序遍历所有的HandlerMapping,找到后立即返回。

配置顺序比如:order越小优先级越高

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

详情

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

AbstractHandlerMapping

HandlerMapping的抽象实现,所有HandlerMapping都继承自它。采用模板模式设计了HandlerMapping实现。

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
		implements HandlerMapping, Ordered{

....省略...
    @Override
    protected void initApplicationContext() throws BeansException {
	//模板方法,用于子类提供一个添加或者修改Interceptors的入口,目前SpringMVC没有实现
        extendInterceptors(this.interceptors);
        //将SpringMVC容器及父容器中的所有MappedInterceptor类型Bean添加到mappedInterceptors属性
	detectMappedInterceptors(this.mappedInterceptors);
        //初始化Interceptor,具体内容其实是将Interceptors属性里所包含的对象按类型添加到mappedInterceptors或者adaptedInterceptors
	initInterceptors();
    }

    protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
	mappedInterceptors.addAll(
		BeanFactoryUtils.beansOfTypeIncludingAncestors(
						getApplicationContext(), MappedInterceptor.class, true, false).values());
    }

    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");
			}
			if (interceptor instanceof MappedInterceptor) {
				this.mappedInterceptors.add((MappedInterceptor) interceptor);
			}
			else {
			this.adaptedInterceptors.add(adaptInterceptor(interceptor));
			}
		}
	}
    }


}

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

AbstractHandlerMapping之用

通过getHandler方法来获取处理器Handler和拦截器Interceptor的

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);
	}
	return getHandlerExecutionChain(handler, request);
}

 【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
		(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
	chain.addInterceptors(getAdaptedInterceptors());
	String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
	for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
	    if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
     		chain.addInterceptor(mappedInterceptor.getInterceptor());
	    }
	}
	return chain;
}

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

AbstractUrlHandlerMapping系列

AbstractUrlHandlerMapping系列都继承自AbstractUrlHandlerMapping;通过url来进行匹配的。大致原理是将url与对应的Handler保存在一个map中,在getHandlerInternal方法中使用url从map中获取Handler。AbstractUrlHandlerMapping中实现了具体用url从map中获取Handler的过程,而map的初始化则交给了具体的子孙类去完成。
private Object rootHandler;

private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
@Override
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 = getApplicationContext().getBean(handlerName);
			}
			validateHandler(rawHandler, 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;
}

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

 【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

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?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = getApplicationContext().getBean(handlerName);
		}
		validateHandler(handler, request);
		return buildPathExposingHandler(handler, urlPath, urlPath, null);
	}
	// Pattern match?
	List<String> matchingPatterns = new ArrayList<String>();
	for (String registeredPattern : this.handlerMap.keySet()) {
		if (getPathMatcher().match(registeredPattern, urlPath)) {
			matchingPatterns.add(registeredPattern);
		}
	}
	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);
		// 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<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);
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
		}
		return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
	}
	// No handler found...
	return null;
}

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

SimpleUrlHandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

AbstractDetectingUrlHandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

AbstractHandlerMethodMapping系列

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping 【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

 【SpringMVC】DispatcherServlet重要组件之一HandlerMapping

【SpringMVC】DispatcherServlet重要组件之一HandlerMapping