protected void doDispatch(HttpServletRequest request
, HttpServletResponse response
) throws Exception
{
HttpServletRequest processedRequest
= request
;
HandlerExecutionChain mappedHandler
= null
;
boolean multipartRequestParsed
= false;
WebAsyncManager asyncManager
= WebAsyncUtils
.getAsyncManager(request
);
try {
ModelAndView mv
= null
;
Exception dispatchException
= null
;
try {
processedRequest
= checkMultipart(request
);
multipartRequestParsed
= (processedRequest
!= request
);
mappedHandler
= getHandler(processedRequest
);
getHandler方法
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
;
}
request中有请求的url
org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
public final HandlerExecutionChain
getHandler(HttpServletRequest request
) throws Exception
{
Object handler
= getHandlerInternal(request
);
if (handler
== null
) {
handler
= getDefaultHandler();
}
if (handler
== null
) {
return null
;
}
if (handler
instanceof String) {
String handlerName
= (String
) handler
;
handler
= obtainApplicationContext().getBean(handlerName
);
}
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());
}
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
;
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal方法
protected HandlerMethod
getHandlerInternal(HttpServletRequest request
) throws Exception
{
String lookupPath
= getUrlPathHelper().getLookupPathForRequest(request
);
this.mappingRegistry
.acquireReadLock();
try {
HandlerMethod handlerMethod
= lookupHandlerMethod(lookupPath
, request
);
return (handlerMethod
!= null
? handlerMethod
.createWithResolvedBean() : null
);
}
finally {
this.mappingRegistry
.releaseReadLock();
}
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod方法
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()) {
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);
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
);
}
}
这里对于结果的匹配,首先会通过uri进行直接匹配,如果能匹配到,则在匹配结果中尝试进行RequestMethod,Consumes和Produces等配置的匹配;如果通过uri不能匹配到,则直接对所有定义的RequestMapping进行匹配,这里主要是进行正则匹配,如果能匹配到。如果能够匹配到,则对匹配结果按照相似度进行排序,并且对前两个结果相似度进行比较,如果相似度一样,则抛出异常,如果不一样,则返回相似度最高的一个匹配结果。如果无法获取到匹配结果,则对所有的匹配结果进行遍历,判断当前request具体是哪一部分参数无法匹配到结果。对于匹配结果的获取,主要在addMatchingMappings()方法中
addMatchingMappings方法
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
.getMappings().get(mapping
)));
}
}
}