之前的一篇HandlerMapping初始化流程觉吭,講述了HandlerMapping的初始化流程掂碱,本文就來看下HandlerMapping的工作流程,主要就是根據(jù)http請(qǐng)求查找到對(duì)應(yīng)的controller岔霸,還會(huì)加上一些攔截器柄粹,然后執(zhí)行攔截器與controller的方法。
springmvc的請(qǐng)求入口都是DispatcherServlet的doDispatch方法,方法內(nèi)部的這行代碼就是請(qǐng)求映射到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中芋绸,循環(huán)容器的所有HandlerMapping,執(zhí)行mapping的getHandler担敌,若不為null摔敛,說明匹配了。這里HandlerMapping的執(zhí)行順序就是通過mapping的order屬性指定的全封,這里返回的是HandlerExecutionChain 對(duì)象马昙,因?yàn)闀?huì)存在一些攔截器,在請(qǐng)求處理方法的前后加一些邏輯刹悴。
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;
}
這個(gè)方法主要有3個(gè)步驟
- 根據(jù)request獲取到handler行楞,若沒匹配上,會(huì)返回容器一個(gè)默認(rèn)的handler
- 找到interceptor颂跨,封裝成HandlerExecutionChain 對(duì)象
- 若有跨域的相關(guān)配置敢伸,則加上跨域的攔截器
先看下第一個(gè)步驟
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//拿到請(qǐng)求的路徑 如:/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();
}
}
根據(jù)請(qǐng)求路徑和請(qǐng)求對(duì)象查找HandlerMethod對(duì)象
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);
}
}
根據(jù)請(qǐng)求路徑去從map查找(上篇文章有詳細(xì)的描述)扯饶,獲取匹配到的RequestMappingInfo列表恒削。最終再拿到一個(gè)HandlerMethod對(duì)象。
找到HandlerMethod對(duì)象后尾序,再查找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時(shí)分判斷是否為MappedInterceptor,這種需要根據(jù)請(qǐng)求路徑做匹配每币,匹配上的才會(huì)添加携丁,還有一種是通用的,每個(gè)請(qǐng)求都會(huì)加上的兰怠,比如ConversionServiceExposingInterceptor
獲取到HandlerExecutionChain后梦鉴,會(huì)根據(jù)是否有跨域配置,若有的話揭保,加上跨域的處理器
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;
}
}
當(dāng)根據(jù)request拿到最終要執(zhí)行的HandlerExecutionChain后肥橙,在執(zhí)行具體的controller的方法前后,及方法執(zhí)行完畢后秸侣,會(huì)先執(zhí)行攔截器的幾個(gè)回調(diào)方法存筏。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//省略.....
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//省略
//拿到HandlerExecutionChain對(duì)象
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//先執(zhí)行攔截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 執(zhí)行具體controller的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//執(zhí)行攔截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
//執(zhí)行攔截器的afterCompletion方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
//即使有異常拋出,也會(huì)執(zhí)行攔截器的afterCompletion方法
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
//省略
}