Spring5 源码阅读笔记(5.2.2)getHandler

类 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);
		//方法上@CrossOrigin注解信息
		CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
		CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
		//往拦截器链里添加new CorsInterceptor(config)
		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 里的值是什么时候放进去的呢?

在这里插入图片描述
同样在这个类里,有个初始化上下文方法:

@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());
	}
}
发布了185 篇原创文章 · 获赞 271 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44367006/article/details/104998598