AbstractHandlerMapping是HandlerMapping的抽象实现,所有HandlerMapping都继承自AbstractHandlerMapping。AbstractHandlerMapping采用模板模式设计了HandlerMapping实现的整体接口,它继承了WebApplicationObjectSupport,初始化时会自动调用模板方法initApplicationContext:
protected void initApplicationContext() throws BeansException {
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);
initInterceptors();
}
extendInterceptors:用于给子类提供一个添加Interceptors的入口
detectMappedInterceptors:用于将SpringMVC容器以及父容器中所有MappedInterceptor类型的Bean添加到mappedInterceptors属性:
protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
getApplicationContext(), MappedInterceptor.class, true, false).values());
}
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");
}
if (interceptor instanceof MappedInterceptor) {
this.mappedInterceptors.add((MappedInterceptor) interceptor);
}
else {
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
}
具体内容就是将interceptors属性里面的对象分类添加到两个集合中
Interceptors:用于配置SpringMVC的拦截器。Interceptors并不会直接使用,而是通过initInterceptors方法按类型分配到mappedInterceptors和adaptedInterceptors再使用
mappedInterceptors:此类Interceptor在使用时会与请求的url进行匹配
adaptedInterceptors:这种类型的Interceptor不需要进行匹配,在getHandler中会全部添加到返回值HandlerExecutionChain里面
HandlerMapping通过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);
}
首先会通过getHandlerInternal根据request获取Handler,然后调用getHandlerExecutionChain返回一个HandlerExecutionChain:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//创建一个HandlerExecutionChain
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//添加所有的adaptedInterceptors
chain.addInterceptors(getAdaptedInterceptors());
//根据路径匹配mappedInterceptor
String lookupPath = this.u rlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
在这个方法中就是先创建一个HandlerExecutionChain,然后将匹配的拦截器都添加进去
AbstractUrlHandlerMapping
它是将url与对应的Handler保存在一个Map中,通过getHandlerInternal返回具体的Handler
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//获取请求的url
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//根据url获取Handler
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
// 根据不同的情况获取Handler
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;
}
下面看一下查找的过程:
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// 首先直接尝试根据url获取handler
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// 如果不为空,那么封装好后直接返回
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}
// 可能是通配符匹配的url
List<String> matchingPatterns = new ArrayList<String>();
//将所有匹配的url添加到集合中
for (String registeredPattern : this.handlerMap.keySet()) {
if (getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
}
//将获取到的url排序,然后选择第一个
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
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);
//可能有多个排名第一个的handler
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;
}
在这个方法中有两个主线,一个是直接查找,找到了直接返回,另一个是通过通配符匹配,匹配出来可能有好多个, 需要对他们进行排序选在最优的那个:
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;
}
在这个方法里面注册了两个拦截器PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor。
下面看一下Map的初始化,初始化一共有两个方法,一个是注册url和Handler的名字,另一个就是注册url和具体的Handler:
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;
// 如果没有设置懒加载并且类型是String,直接从容器中获取,并添加到Map中
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
if (getApplicationContext().isSingleton(handlerName)) {
resolvedHandler = getApplicationContext().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.");
}
}
else {
if (urlPath.equals("/")) {
if (logger.isInfoEnabled()) {
logger.info("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
else if (urlPath.equals("/*")) {
if (logger.isInfoEnabled()) {
logger.info("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isInfoEnabled()) {
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}
下面看一个它的子类SimpleUrlHandlerMapping,他重写了initApplicationContext方法:
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
registerHandlers(this.urlMap);
}
首先调用了父类的initApplicationContext方法,然后将自己Map里面的Handler注册到父类的Map中
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);
}
}
}
AbstractDetectingUrlHandlerMapping也是AbstractUrlHandlerMapping的子类,也是通过重写initApplicationContext注册Handler:
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
detectHandlers();
}
protected void detectHandlers() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
}
//获取容器中所有的beanName
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
//匹配所有的beanName
for (String beanName : beanNames) {
String[] urls = determineUrlsForHandler(beanName);
if (!ObjectUtils.isEmpty(urls)) {
// 注册到父类的Map中
registerHandler(urls, beanName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
}
}
}
}
通过detectHandlers方法, 根据配置的detectHandlerInAncestorContexts参数从SpringMVC容器或者SpringMVC及其父容器中找到所有bean的beanName,然后用determineUrlsForHandler方法对每个beanName解析出对应的urls,如果解析结果不为空则将解析出的urls个beanName注册到父类的Map。
AbstractHandlerMapping的另一个分支就是AbstractHandlerMethodMapping,它是将Method作为Handler来使用,就是我们用@RequestMapping注释的方法
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
//获取所有的beanName
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
isHandler(getApplicationContext().getType(beanName))){
//将符合条件的beanName进行处理
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
首先拿到容器中的所有bean,然后根据一定的规则筛选出Handler,最后保存到Map里面,筛选使用的方法是isHandler,就是判断是否有Controller或者RequestMapping注释
protected void detectHandlerMethods(final Object handler) {
//获取当前Handler的class对象
Class<?> handlerType =
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());
// 用于保存方法和条件
final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
final Class<?> userType = ClassUtils.getUserClass(handlerType);
//选择所有符合过滤条件的method
Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
@Override
public boolean matches(Method method) {
//获取method的匹配条件
T mapping = getMappingForMethod(method, userType);
if (mapping != null) {
mappings.put(method, mapping);
return true;
}
else {
return false;
}
}
});
//注册到Map中
for (Method method : methods) {
registerHandlerMethod(handler, method, mappings.get(method));
}
}
在这个方法中做了两件事:
1、从传入的处理器中找到符合要求的方法
2、注册
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = null;
//获取方法上的RequestMapping的注释
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (methodAnnotation != null) {
//封装方法的匹配条件
RequestCondition<?> methodCondition = getCustomMethodCondition(method);
info = createRequestMappingInfo(methodAnnotation, methodCondition);
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
if (typeAnnotation != null) {
RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
}
}
return info;
}
我们发现在验证这个方法是否符合要求主要是根据是否有RequestMapping注释
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
//封装handler和当前method
HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);
//获取当前匹配条件对应的HandlerMethod
HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping);
if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) {
throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() +
"' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" +
oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped.");
}
//将新的HandlerMethod 添加到map中
this.handlerMethods.put(mapping, newHandlerMethod);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);
}
//获取匹配条件集合
Set<String> patterns = getMappingPathPatterns(mapping);
for (String pattern : patterns) {
//添加到map中
if (!getPathMatcher().isPattern(pattern)) {
this.urlMap.add(pattern, mapping);
}
}
//将name和HandlerMethod 添加到Map中
if (this.namingStrategy != null) {
String name = this.namingStrategy.getName(newHandlerMethod, mapping);
updateNameMap(name, newHandlerMethod);
}
}
下面看一下是如何找到对应的处理器的:
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获得url
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
//从map中找到对应的HandlerMethod
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 + "]");
}
}
//如果找到了创建要给新的HandlerMethod返回
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
我们看这个方法里面一共做了三件事:
1、获取url
2、获取对应的HandlerMethod
3、如果找到了创建一个新的HandlerMethod返回
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<Match>();
//从Map中找到当前url对应的所有过滤条件
List<T> directPathMatches = this.urlMap.get(lookupPath);
//将条件添加到matches中
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.handlerMethods.keySet(), matches, request);
}
if (!matches.isEmpty()) {
//对所有匹配条件进行排序,选取排名最好的那个
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
Collections.sort(matches, comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
}
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException(
"Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" +
m1 + ", " + m2 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
}
}