1. 程式人生 > >springMVC原始碼分析--HandlerInterceptor攔截器呼叫過程(二)

springMVC原始碼分析--HandlerInterceptor攔截器呼叫過程(二)

在上一篇部落格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所提供的方法。