欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring5 源码阅读笔记(5.2.2)getHandler

程序员文章站 2022-03-06 08:06:38
...

类 DispatcherServlet

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	//handlerMappering实例
	if (this.handlerMappings != null) {
		for (HandlerMapping mapping : this.handlerMappings) {
			//获取HandlerMethod和过滤器链的包装类
			HandlerExecutionChain handler = mapping.getHandler(request);
			if (handler != null) {
				//优先级高的handlerMappering能处理直接返回
				return handler;
			}
		}
	}
	return null;
}

跟 getHandler:
AbstractHandlerMapping

@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	//根据请求的uri拿到对应的HandlerMethod对象 见5.2.2.1
	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 = obtainApplicationContext().getBean(handlerName);
	}

	//获取HandlerMethod和过滤器链的包装类     见5.2.2.2
	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());
	}

	//是否是跨域请求,就是查看request请求头中是否有Origin属性
	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;
}

类 AbstractHandlerMethodMapping< T >,它实现了 InitializingBean 接口,意味着肯定重写了 afterPropertiesSet 方法,见 Spring5 源码阅读笔记(5.2.1)AbstractHandlerMapping 里的 afterPropertiesSet

5.2.2.1 getHandlerInternal

有请求过来之后

@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	//从request对象中获取uri
	String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
	this.mappingRegistry.acquireReadLock();
	try {
		//根据uri从映射关系中找到对应的HandlerMethod对象
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		//把Controller类实例化
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		this.mappingRegistry.releaseReadLock();
	}
}

跟 lookupHandlerMethod:

@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<>();
	List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
	if (directPathMatches != null) {
		addMatchingMappings(directPathMatches, matches, request);
	}
	if (matches.isEmpty()) {
		// No choice but to go through all mappings...
		addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
	}

	if (!matches.isEmpty()) {
		Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
		matches.sort(comparator);
		Match bestMatch = matches.get(0);
		if (matches.size() > 1) {
			if (logger.isTraceEnabled()) {
				logger.trace(matches.size() + " matching mappings: " + matches);
			}
			if (CorsUtils.isPreFlightRequest(request)) {
				return PREFLIGHT_AMBIGUOUS_MATCH;
			}
			Match secondBestMatch = matches.get(1);
			//如果两个RequestMappinginfo什么都相同,报错
			if (comparator.compare(bestMatch, secondBestMatch) == 0) {
				Method m1 = bestMatch.handlerMethod.getMethod();
				Method m2 = secondBestMatch.handlerMethod.getMethod();
				String uri = request.getRequestURI();
				throw new IllegalStateException(
						"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
			}
		}
		request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
		handleMatch(bestMatch.mapping, lookupPath, request);
		return bestMatch.handlerMethod;
	}
	else {
		return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
	}
}

跟 addMatchingMappings:

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
	for (T mapping : mappings) {
		//T:RequestMappingInfo,如果@RequestMapping和request不匹配就会返回null
		T match = getMatchingMapping(mapping, request);
		if (match != null) {
			//RequestMappingInfo对象和HandlerMethod对象封装到Match对象中
			matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
		}
	}
}

5.2.2.2 getHandlerExecutionChain

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	//把HandlerMethod对象包装到HandlerExecutionChain对象中,这个对象中有一个拦截器数组
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

	//获取uri
	String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);

	//是否有拦截器
	for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
		if (interceptor instanceof MappedInterceptor) {
			MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
			if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
				chain.addInterceptor(mappedInterceptor.getInterceptor());
			}
		}
		else {
			chain.addInterceptor(interceptor);
		}
	}
	return chain;
}

adaptedInterceptors 里的拦截器哪里来的?

Spring5 源码阅读笔记(5)基于注解的方法替换spring-dispatcher.xml 里已经介绍了,interceptors 里面是有值的。那么 adaptedInterceptors 里的值是什么时候放进去的呢?

Spring5 源码阅读笔记(5.2.2)getHandler
同样在这个类里,有个初始化上下文方法:

@Override
protected void initApplicationContext() throws BeansException {
	extendInterceptors(this.interceptors);
	detectMappedInterceptors(this.adaptedInterceptors);
	//初始化上下文时,就会调用
	initInterceptors();
}

跟 initInterceptors:

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");
			}
										//对interceptor进行了适配操作
			this.adaptedInterceptors.add(adaptInterceptor(interceptor));
		}
	}

跟 adaptInterceptor:

//判断实现了哪个接口
protected HandlerInterceptor adaptInterceptor(Object interceptor) {
	if (interceptor instanceof HandlerInterceptor) {
		return (HandlerInterceptor) interceptor;
	}
	else if (interceptor instanceof WebRequestInterceptor) {
		return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
	}
	else {
		throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
	}
}
相关标签: # MVC