protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
/**
* 声明变量 HttpServletRequest HandlerExecutionChain Handler执行链包含和最扣执行的Handler
*/
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
//是不是一个多组件请求
boolean multipartRequestParsed = false;
//异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
//视图
ModelAndView mv = null;
//异常
Exception dispatchException = null;
try {
/**
* 1.检查是否上传请求
*/
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
/**
* 2.根据processedRequest获取映射的Handler执行链 HandlerExecutionChain
* 有当前请求的Handler和Inteceptor
*/
mappedHandler = getHandler(processedRequest);
getHandler方法
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
/**
* 遍历handlerMappings 映射器
*/
for (HandlerMapping mapping : this.handlerMappings) {
//根据请求获取HandlerExecutionChain
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 {
/**
* 根据请求获取Handler
*/
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);
}
/**
* 获取HandlerExecutionChain
*/
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 {
/**
* 获取请求的url如 /demo/handler01
*/
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
this.mappingRegistry.acquireReadLock();
try {
/**
* 查询和url reqeust匹配的HandlerMthod
*/
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<>();
/**
* 根据URL获取匹配 ,可以匹配到多个
* 通过uri直接在注册的RequestMapping中获取对应的RequestMappingInfo列表,需要注意的是,
* 这里进行查找的方式只是通过url进行查找,但是具体哪些RequestMappingInfo是匹配的,还需要进一步过滤
*/
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
/**
* 如果匹配的就添到上面的集合中
*/
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// 如果无法通过uri进行直接匹配,则对所有的注册的RequestMapping进行匹配,这里无法通过uri
// 匹配的情况主要有三种:
// ①在RequestMapping中定义的是PathVariable,如/user/detail/{id};
// ②在RequestMapping中定义了问号表达式,如/user/?etail;
// ③在RequestMapping中定义了*或**匹配,如/user/detail/**
// 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);
/**
* 会判断前两个是否相似度是一样的,如果是一样的,则直接抛出异常,如果不相同,
*/
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);
//这里主要是对匹配结果的一个处理,主要包含对传入参数和返回的MediaType的处理
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)));
}
}
}