springMVC5.1.5拦截器执行流程源码解析

核心对象HandlerExecutionChain简介

public class HandlerExecutionChain {
    private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
    private final Object handler; // 处理器(可以理解为Controller中定义的映射方法的封装)
    @Nullable
    private HandlerInterceptor[] interceptors;// 拦截器数组
    @Nullable
    private List<HandlerInterceptor> interceptorList;// 拦截器集合
    private int interceptorIndex;// 索引,表示当前拦截器链执行到哪一个了
    
	省略。。。。。。

	// 按顺序执行拦截器链的所有前置方法
	 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
	        HandlerInterceptor[] interceptors = this.getInterceptors();
	        if (!ObjectUtils.isEmpty(interceptors)) {
	        // 每执行一个拦截器索引interceptorIndex就会+1
	            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;
	    }
	// 倒序执行拦截器链的所有后置方法
	   void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
	        HandlerInterceptor[] interceptors = this.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);
	            }
	        }
	
	    }
	// 倒叙执行拦截器链的最终方法,一定会被执行,只会执行执行过前置方法的拦截器,通过所有interceptorIndex来控制
	    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
	        HandlerInterceptor[] interceptors = this.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);
	                } catch (Throwable var8) {
	                    logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
	                }
	            }
	        }
	
	    }
	    
	省略。。。。。。
}

拦截器链执行流程源码分析

拦截器的执行是在DispatcherServlet的doDispatch()方法中执行的:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	  HttpServletRequest processedRequest = request;
	  // 处理器执行链  (拦截器链和处理器(可以看作Controller中配置的映射方法)组成的链)
	   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;
	               mappedHandler = this.getHandler(processedRequest);
	               if (mappedHandler == null) {
	                   this.noHandlerFound(processedRequest, response);
	                   return;
	               }
	
	               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 ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
	                       return;
	                   }
	               }
				// 执行拦截器链路所有前置方法,如果返回false后面的都不执行
	               if (!mappedHandler.applyPreHandle(processedRequest, response)) {
	                   return;
	               }
				/*
	                通过HandlerAdapter(默认实体为RequestMappingHandlerAdapter对象)对象得到ModelAndView对象,
	                该方法最终会调用到容器中配置的映射方法(即处理器),也就是说这一步的时候我们自己在Controller
	                中定义的方法就会被执行
             	*/
	               mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
	               if (asyncManager.isConcurrentHandlingStarted()) {
	                   return;
	               }
	
	               this.applyDefaultViewName(processedRequest, mv);
	               // 执行拦截器后置方法,如果前面的代码出现异常则不会执行此方法,因此后置方法不是一定会被执行的
	               mappedHandler.applyPostHandle(processedRequest, response, mv);
	           } catch (Exception var20) {
	               dispatchException = var20;
	           } catch (Throwable var21) {
	               dispatchException = new NestedServletException("Handler dispatch failed", var21);
	           }
			// 该方法负责视图解析和异常处理,然后执行最终方法,如果出现异常,则会在catch代码块中再次执行最终方法,保证最终方法一定会被执行。
	           this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
	       } catch (Exception var22) {
	       	/*
	             如果processDispatchResult方法中出现异常,保证拦截器中的最终方法一定会被执行,
	             并把processDispatchResult方法中出现的异常传入后置方法,
	             区分:此方法中的异常对象是processDispatchResult方法中产生的异常对象,并不是处理器的执行方法产生的异常对象
         	*/
	           this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
	       } catch (Throwable var23) {
	           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);
	       }
	
	   }
}

你可能感兴趣的:(springMVC5.1.5拦截器执行流程源码解析)