SpringMVC源码解析(二)

RequestMappingHandlerMapping

  RequestMappingHandlerMapping的类继承关系如图所示,图中列出了加载RequestMapping查找Handler的关键方法。 

1、注册Handler      

AbstractHandlerMethodMapping实现了InitializingBean,在初始化后执行afterPropertiesSet()方法,该方法就是将RequestMapping注解的方法、请求参数、请求类型、请求头以及对应的Controller注册到MappingRegistry中。源码的具体实现逻辑如下:

protected void initHandlerMethods() {
	if (logger.isDebugEnabled()) {
		logger.debug("Looking for request mappings in application context: " + getApplicationContext());
	}
	String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
			BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
			getApplicationContext().getBeanNamesForType(Object.class));

	for (String beanName : beanNames) {
		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
			Class<?> beanType = null;
			try {
				beanType = getApplicationContext().getType(beanName);
			}
			catch (Throwable ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
				}
			}
			if (beanType != null && isHandler(beanType)) {
				detectHandlerMethods(beanName);
			}
		}
	}
	handlerMethodsInitialized(getHandlerMethods());
}
//注册handler、method、mapping
//将handler注册到mappingRegistry(4.3.10版本)
protected void detectHandlerMethods(final Object handler) {
	Class<?> handlerType = (handler instanceof String ?
			getApplicationContext().getType((String) handler) : handler.getClass());
	final Class<?> userType = ClassUtils.getUserClass(handlerType);

	Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
			new MethodIntrospector.MetadataLookup<T>() {
				@Override
				public T inspect(Method method) {
					//getMappingForMethod交给具体的子类实现
					return getMappingForMethod(method, userType);
				}
			});

	if (logger.isDebugEnabled()) {
		logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
	}
	for (Map.Entry<Method, T> entry : methods.entrySet()) {
		//handler:对应的Controller的class
		//entry.getKey():对应的请求RequestMapping的请求方法Method
		//entry.getValue():RequestMappingInfo,保存了请求的url、http请求方法、请求参数、header等信息
		registerHandlerMethod(handler, entry.getKey(), entry.getValue());
	}
}
//注册HandlerMethod
protected void registerHandlerMethod(Object handler, Method method, T mapping) {                            
	HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);                                  
	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.");                  
	}                                                                                                       
    //此处的泛型mapping其实就是RequestMappingInfo                                                                                                        
	this.handlerMethods.put(mapping, newHandlerMethod);                                                     
	if (logger.isInfoEnabled()) {                                                                           
		logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);                                   
	}                                                                                                       
    //                                                                                                        
	Set<String> patterns = getMappingPathPatterns(mapping);                                                 
	for (String pattern : patterns) {                                                                       
		if (!getPathMatcher().isPattern(pattern)) {
			//绑定pattern与RequestMappingInfo                                                           
			this.urlMap.add(pattern, mapping);                                                                  
		}                                                                                                     
	}                                                                                                       
}
//创建HandlerMethod
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
	HandlerMethod handlerMethod;
	if (handler instanceof String) {
		String beanName = (String) handler;
		handlerMethod = new HandlerMethod(beanName, getApplicationContext(), method);
	}
	else {
		handlerMethod = new HandlerMethod(handler, method);
	}
	return handlerMethod;
}

   RequestMappingHandlerMapping实现了getMappingForMethod方法,其实就是将@RequestMapping注解中的url、headers、params等包装成RequestMappingInfo,源码如下:

@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
	RequestMappingInfo info = createRequestMappingInfo(method);
	if (info != null) {
		RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
		if (typeInfo != null) {
			info = typeInfo.combine(info);
		}
	}
	return info;
}
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
	RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
	RequestCondition<?> condition = (element instanceof Class<?> ?
			getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
	return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
	
protected RequestMappingInfo createRequestMappingInfo(
		RequestMapping requestMapping, RequestCondition<?> customCondition) {

	return RequestMappingInfo
			.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
			.methods(requestMapping.method())
			.params(requestMapping.params())
			.headers(requestMapping.headers())
			.consumes(requestMapping.consumes())
			.produces(requestMapping.produces())
			.mappingName(requestMapping.name())
			.customCondition(customCondition)
			.options(this.config)
			.build();
}

2、查找Handler

 AbstractHandlerMapping最终返回的是HandlerExecutionChain,是对HandlerMethod与Interceptor的进一步包装,代码的具体实现如下:

@Override
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);
}
//子类AbstractHandlerMethodMapping具体实现方法getHandlerInternal:
@Override
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);
	}
	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 + "]");
		}
	}
	return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
//根据请求url查找对应的HandlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	//匹配的HandlerMethod
	List<Match> matches = new ArrayList<Match>();
	//directPathMatches为RequestMapingInfo集合
	List<T> directPathMatches = this.urlMap.get(lookupPath);
	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);
	}
}

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
	for (T mapping : mappings) {
		T match = getMatchingMapping(mapping, request);
		if (match != null) {
			//match实际类型RequestMapingInfo
			matches.add(new Match(match, this.handlerMethods.get(mapping)));
		}
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值