前幾天學習了spring中異常處理器是怎麼加載進DispatcherServlet並且怎麼處理異常的,以及過濾器的原理。今天看下攔截器是怎麼工作的,都知道是在DispatcherServlet中執行handler的方法前後會執行攔截器的prehandle和posthandle方法,那麼是怎麼加載進DispatcherServlet以及怎麼執行的呢?
加載入DispatcherServlet
DispatcherServlet初始化時,調用onRefresh
方法,裏面調用initStrategies
的this.initHandlerMappings(context);
方法中實際加載攔截器。
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
initHandlerMappings方法會加載所有實現HandlerMapping的類。
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
} else {
try {
HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
在doDispatch
方法中,mappedHandler = this.getHandler(processedRequest);
實際是調用抽象類AbstractHandlerMapping
的public final HandlerExecutionChain getHandler(HttpServletRequest request)
方法,獲取了一個HandlerExecutionChain對象,把匹配request的url的攔截器都加入HandlerExecutionChain。
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Iterator var5 = this.adaptedInterceptors.iterator();
while(var5.hasNext()) {
HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
chain.addInterceptor(interceptor);
}
}
執行
攔截器的preHandle
方法實際是調用HandlerExecutionChain對象的applyPreHandle
方法,這個調用是在HandlerAdapter對象的handle方法也就是contrller本身的方法調用之前。postHandle
在之後,最後在processDispatchResult
處理返回結果和抓異常時執行攔截器的afterCompletion
方法。
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
附上doDispatch方法:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//包含了一個匹配改url的攔截器list
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//這個是實際controller的代理類
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
//執行preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//實際controller方法的執行
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
//執行postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
//處理返回結果並執行攔截器的afterCompletion方法,如果exception不爲null則執行HandlerExceptionResolver的邏輯
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
//執行攔截器的afterCompletion方法
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
//執行攔截器的afterCompletion方法
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}