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
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。