首页 > 编程语言 >SpringMVC源码-getHandler

SpringMVC源码-getHandler

时间:2022-11-05 16:56:19浏览次数:57  
标签:HttpServletRequest return String SpringMVC handler request 源码 getHandler null

DispatcherServlet.getHandler(HttpServletRequest request)

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	if (this.handlerMappings != null) {
		for (HandlerMapping mapping : this.handlerMappings) {
			HandlerExecutionChain handler = mapping.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
	}
	return null;
}

如果handlerMappings不为null,从handlerMappings中找出处理当前请求的HandlerExecutionChain并返回。handlerMappings集合的元素分别是RequestMappingHandlerMapping,BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping。

一、RequestMappingHandlerMapping

AbstractHandlerMapping.getHandler(HttpServletRequest request)

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 = obtainApplicationContext().getBean(handlerName);
	}

	// Ensure presence of cached lookupPath for interceptors and others
	if (!ServletRequestPathUtils.hasCachedPath(request)) {
		initLookupPath(request);
	}

	HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

	if (logger.isTraceEnabled()) {
		logger.trace("Mapped to " + handler);
	}
	else if (logger.isDebugEnabled() && !DispatcherType.ASYNC.equals(request.getDispatcherType())) {
		logger.debug("Mapped to " + executionChain.getHandler());
	}

	if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
		CorsConfiguration config = getCorsConfiguration(handler, request);
		if (getCorsConfigurationSource() != null) {
			CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
			config = (globalConfig != null ? globalConfig.combine(config) : config);
		}
		if (config != null) {
			config.validateAllowCredentials();
		}
		executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
	}

	return executionChain;
}

1、getHandlerInternal获取handle,如果handle为null则getDefaultHandler获取默认handle,handle还为null返回。
2、如果handle是String,handle可能为beanName,调用getBean获取bean
3、如果拦截器没有缓存查找路径就initLookupPath解析拦截器路径并缓存。
4、获取HandlerExecutionChain
5、如果有CORS配置则处理CORS

RequestMappingInfoHandlerMapping.getHandlerInternal(HttpServletRequest request)

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
	try {
		return super.getHandlerInternal(request);
	}
	finally {
		ProducesRequestCondition.clearMediaTypesAttribute(request);
	}
}

AbstractHandlerMethodMapping.getHandlerInternal(HttpServletRequest request)

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	String lookupPath = initLookupPath(request);
	this.mappingRegistry.acquireReadLock();
	try {
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		this.mappingRegistry.releaseReadLock();
	}
}

1、initLookupPath查找request请求路径
2、lookupHandlerMethod查找请求路径处理方法HandlerMethod
3、如果HandlerMethod不为null则handlerMethod.createWithResolvedBean解析处理方法对应的bean。

AbstractHandlerMethodMapping.initLookupPath(HttpServletRequest request)

protected String initLookupPath(HttpServletRequest request) {
	if (usesPathPatterns()) {
		request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);
		RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);
		String lookupPath = requestPath.pathWithinApplication().value();
		return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);
	}
	else {
		return getUrlPathHelper().resolveAndCacheLookupPath(request);
	}
}

1、如果usesPathPatterns()为true,调用ServletRequestPathUtils.getParsedRequestPath解析lookupPath。usesPathPatterns()默认为false。
2、调用getUrlPathHelper().resolveAndCacheLookupPath解析lookupPath

UrlPathHelper.resolveAndCacheLookupPath(HttpServletRequest request)

public String resolveAndCacheLookupPath(HttpServletRequest request) {
	String lookupPath = getLookupPathForRequest(request);
	request.setAttribute(PATH_ATTRIBUTE, lookupPath);
	return lookupPath;
}

1、getLookupPathForRequest解析request对应的请求路径
2、PATH_ATTRIBUTE为key,请求路径lookupPath为value设置属性到request中

UrlPathHelper.getLookupPathForRequest(HttpServletRequest request)

  public String getLookupPathForRequest(HttpServletRequest request) {
	String pathWithinApp = getPathWithinApplication(request);
	// Always use full path within current servlet context?
	if (this.alwaysUseFullPath || skipServletPathDetermination(request)) {
		return pathWithinApp;
	}
	// Else, use path within current servlet mapping if applicable
	String rest = getPathWithinServletMapping(request, pathWithinApp);
	if (StringUtils.hasLength(rest)) {
		return rest;
	}
	else {
		return pathWithinApp;
	}
}

1、getPathWithinApplication从request中返回请求路径
2、如果使用全路径或skipServletPathDetermination为true则返回,skipServletPathDetermination检查是否可跳过请求路径
3、getPathWithinServletMapping使用当前Servlet中映射的路径

UrlPathHelper.getPathWithinApplication(HttpServletRequest request)

public String getPathWithinApplication(HttpServletRequest request) {
	String contextPath = getContextPath(request);
	String requestUri = getRequestUri(request);
	String path = getRemainingPath(requestUri, contextPath, true);
	if (path != null) {
		// Normal case: URI contains context path.
		return (StringUtils.hasText(path) ? path : "/");
	}
	else {
		return requestUri;
	}
}

1、getContextPath从request获取contextPath
2、getRequestUri从request获取requestUri
3、getRemainingPath从requestUri中去掉contextPath剩余部分,如requestUri为/myself-web/userParam0,contextPath为/myself-web,getRemainingPath(requestUri, contextPath, true)结果为/userParam0

UrlPathHelper.getContextPath(HttpServletRequest request)

public String getContextPath(HttpServletRequest request) {
	String contextPath = (String) request.getAttribute(WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE);
	if (contextPath == null) {
		contextPath = request.getContextPath();
	}
	if (StringUtils.matchesCharacter(contextPath, '/')) {
		// Invalid case, but happens for includes on Jetty: silently adapt it.
		contextPath = "";
	}
	return decodeRequestString(request, contextPath);
}

1、从request中获取INCLUDE_CONTEXT_PATH_ATTRIBUTE属性,如果为null则从request中获取contextPath
2、decodeRequestString解码contextPath

UrlPathHelper.getRequestUri(HttpServletRequest request)

public String getRequestUri(HttpServletRequest request) {
	String uri = (String) request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE);
	if (uri == null) {
		uri = request.getRequestURI();
	}
	return decodeAndCleanUriString(request, uri);
}

1、从request中获取INCLUDE_REQUEST_URI_ATTRIBUTE属性,如果为null则从request中获取RequestURI
2、decodeAndCleanUriString解码RequestURI

UrlPathHelper.skipServletPathDetermination(HttpServletRequest request)

private boolean skipServletPathDetermination(HttpServletRequest request) {
	if (servlet4Present) {
		return Servlet4Delegate.skipServletPathDetermination(request);
	}
	return false;
}

如果servlet4Present为true,调用Servlet4Delegate.skipServletPathDetermination检查是否可跳过请求路径,否则返回false。

Servlet4Delegate.skipServletPathDetermination(HttpServletRequest request)

public static boolean skipServletPathDetermination(HttpServletRequest request) {
		HttpServletMapping mapping = (HttpServletMapping) request.getAttribute(RequestDispatcher.INCLUDE_MAPPING);
		if (mapping == null) {
			mapping = request.getHttpServletMapping();
		}
		MappingMatch match = mapping.getMappingMatch();
		return (match != null && (!match.equals(MappingMatch.PATH) || mapping.getPattern().equals("/*")));
	}

获取MappingMatch,判断MappingMatch是否匹配MappingMatch.PATH(MappingMatch.PATH是/faces/这种的映射路径)和HttpServletMapping获取pattern是否和/相等。

AbstractHandlerMethodMapping.lookupHandlerMethod(String lookupPath, HttpServletRequest request)

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<>();
	List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
	if (directPathMatches != null) {
		addMatchingMappings(directPathMatches, matches, request);
	}
	if (matches.isEmpty()) {
		addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
	}
	if (!matches.isEmpty()) {
		Match bestMatch = matches.get(0);
		if (matches.size() > 1) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			matches.sort(comparator);
			bestMatch = matches.get(0);
			if (logger.isTraceEnabled()) {
				logger.trace(matches.size() + " matching mappings: " + matches);
			}
			if (CorsUtils.isPreFlightRequest(request)) {
				for (Match match : matches) {
					if (match.hasCorsConfig()) {
						return PREFLIGHT_AMBIGUOUS_MATCH;
					}
				}
			}
			else {
				Match secondBestMatch = matches.get(1);
				if (comparator.compare(bestMatch, secondBestMatch) == 0) {
					Method m1 = bestMatch.getHandlerMethod().getMethod();
					Method m2 = secondBestMatch.getHandlerMethod().getMethod();
					String uri = request.getRequestURI();
					throw new IllegalStateException(
							"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
				}
			}
		}
		request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
		handleMatch(bestMatch.mapping, lookupPath, request);
		return bestMatch.getHandlerMethod();
	}
	else {
		return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
	}
}

1、mappingRegistry.getMappingsByDirectPath通过请求路径获取RequestMappingInfo集合
2、如果RequestMappingInfo集合不为null,调用addMatchingMappings添加Match集合
3、如果matches为空,addMatchingMappings从mappingRegistry.getRegistrations().keySet()中添加Match匹配request的集合
4、如果matches集合非空,查找最匹配的Match,调用handleMatch处理Match。handleMatch在请求中公开URI模板变量、矩阵变量和可生产的媒体类型。如果matches集合为空,handleNoMatch处理没有Match的情况。

AbstractHandlerMethodMapping.addMatchingMappings(Collection mappings, List matches, HttpServletRequest request)

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
	for (T mapping : mappings) {
		T match = getMatchingMapping(mapping, request);
		if (match != null) {
			matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));
		}
	}
}

遍历mappings集合,getMatchingMapping返回匹配请求的RequestMappingInfo加到Match集合中。

RequestMappingInfoHandlerMapping.getMatchingMapping(RequestMappingInfo info, HttpServletRequest request)

protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
	return info.getMatchingCondition(request);
}

返回匹配请求的RequestMappingInfo。

AbstractHandlerMapping.getHandlerExecutionChain(Object handler, HttpServletRequest request)

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

	for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
		if (interceptor instanceof MappedInterceptor) {
			MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
			if (mappedInterceptor.matches(request)) {
				chain.addInterceptor(mappedInterceptor.getInterceptor());
			}
		}
		else {
			chain.addInterceptor(interceptor);
		}
	}
	return chain;
}

1、创建HandlerExecutionChain
2、遍历adaptedInterceptors,如果interceptor是MappedInterceptor类型且匹配request,则获取Interceptor加入到HandlerExecutionChain,如果interceptor不是MappedInterceptor类型加入HandlerExecutionChain。

标签:HttpServletRequest,return,String,SpringMVC,handler,request,源码,getHandler,null
From: https://www.cnblogs.com/shigongp/p/16860019.html

相关文章