之前的一篇HandlerMapping初始化流程,讲述了HandlerMapping的初始化流程,本文就来看下HandlerMapping的工作流程,主要就是根据http请求查找到对应的controller,还会加上一些拦截器,然后执行拦截器与controller的方法。
springmvc的请求入口都是DispatcherServlet的doDispatch方法,方法内部的这行代码就是请求映射到handler处理逻辑
mappedHandler = getHandler(processedRequest);
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;
}
getHandler中,循环容器的所有HandlerMapping,执行mapping的getHandler,若不为null,说明匹配了。这里HandlerMapping的执行顺序就是通过mapping的order属性指定的,这里返回的是HandlerExecutionChain 对象,因为会存在一些拦截器,在请求处理方法的前后加一些逻辑。
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);
}
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
这个方法主要有3个步骤
- 根据request获取到handler,若没匹配上,会返回容器一个默认的handler
- 找到interceptor,封装成HandlerExecutionChain 对象
- 若有跨域的相关配置,则加上跨域的拦截器
先看下第一个步骤
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//拿到请求的路径 如:/student/getStudent
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
根据请求路径和请求对象查找HandlerMethod对象
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()) {
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)) {
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);
}
}
根据请求路径去从map查找(上篇文章有详细的描述),获取匹配到的RequestMappingInfo列表。最终再拿到一个HandlerMethod对象。
找到HandlerMethod对象后,再查找interceptor,封装成HandlerExecutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
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;
}
添加interceptor时分判断是否为MappedInterceptor,这种需要根据请求路径做匹配,匹配上的才会添加,还有一种是通用的,每个请求都会加上的,比如ConversionServiceExposingInterceptor
获取到HandlerExecutionChain后,会根据是否有跨域配置,若有的话,加上跨域的处理器
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
HandlerExecutionChain chain, @Nullable CorsConfiguration config) {
if (CorsUtils.isPreFlightRequest(request)) {
HandlerInterceptor[] interceptors = chain.getInterceptors();
return new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
}
else {
chain.addInterceptor(0, new CorsInterceptor(config));
return chain;
}
}
当根据request拿到最终要执行的HandlerExecutionChain后,在执行具体的controller的方法前后,及方法执行完毕后,会先执行拦截器的几个回调方法。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//省略.....
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//省略
//拿到HandlerExecutionChain对象
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//先执行拦截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行具体controller的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//执行拦截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
//执行拦截器的afterCompletion方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
//即使有异常抛出,也会执行拦截器的afterCompletion方法
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
//省略
}
网友评论