springMVC原始碼分析--HandlerInterceptor攔截器呼叫過程(二)
阿新 • • 發佈:2019-01-10
在上一篇部落格springMVC原始碼分析--HandlerInterceptor攔截器(一)中我們介紹了HandlerInterceptor攔截器相關的內容,瞭解到了HandlerInterceptor提供的三個介面方法:
(1)preHandle: 在執行controller處理之前執行,返回值為boolean ,返回值為true時接著執行postHandle和afterCompletion,如果我們返回false則中斷執行
(2)postHandle:在執行controller的處理後,在ModelAndView處理前執行
(3)afterCompletion :在DispatchServlet執行完ModelAndView之後執行
我們可以看到這三個方法的呼叫過程是不一樣的,接下來我們分析一下這個三個方法具體呼叫實現的地方。其最終實現呼叫的地方是在doDispatch函式中,因為doDispatch完成了一個請求到返回資料的完整操作。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerExecutionChain mappedHandler = null; ....... try { ModelAndView mv = null; Exception dispatchException = null; try { ....... //獲取HandlerExecutionChain mappedHandler = getHandler(processedRequest); ...... //最終會呼叫HandlerInterceptor的preHandle方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //
呼叫具體的Controller中的處理方法Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); ...... //最終會呼叫HandlerInterceptor的postHandle方法 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { //最終會呼叫HandlerInterceptor的afterCompletion 方法 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { //最終會呼叫HandlerInterceptor的afterCompletion 方法 triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
mappedHandler.applyPreHandle(processedRequest, response):最終會呼叫HandlerInterceptor的preHandle方法。在HandlerExecutionChain中的具體實現如下,我們可以看到會呼叫所有的HandlerInterceptor攔截器並呼叫其preHandler方法。
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();//獲取所有的攔截器
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {//分別呼叫攔截器的preHandle方法
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
mappedHandler.applyPostHandle(processedRequest, response, mv):最終會呼叫HandlerInterceptor的postHandle方法
具體實現是在HandlerExecutionChain中實現如下,就是獲取所有的攔截器並呼叫其postHandle方法。
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();//獲取所有攔截器
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);//分別呼叫攔截器的postHandle方法
}
}
}
triggerAfterCompletion(processedRequest, response, mappedHandler, ex):最終會呼叫HandlerInterceptor的afterCompletion 方法triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err):最終會呼叫HandlerInterceptor的afterCompletion 方法
private void triggerAfterCompletionWithError(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, Error error) throws Exception {
ServletException ex = new NestedServletException("Handler processing failed", error);
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, ex);
}
throw ex;
}
private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, Exception ex) throws Exception {
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, ex);
}
throw ex;
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();//獲取所有攔截器
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);//呼叫攔截器的afterCompletion方法
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
通過以上程式碼分析我們可以看到HandlerInterceptor攔截器的最終呼叫實現是在DispatcherServlet的doDispatch方法中,並且SpringMVC提供了HandlerExecutionChain來幫助我們執行所有配置的HandlerInterceptor攔截器,並分別呼叫HandlerInterceptor所提供的方法。