转自:https://blog.csdn.net/qq_25673113/article/details/79153547
Interceptor拦截器用于拦截Controller层接口,表现形式有点像Spring的AOP,但是AOP是针对单一的方法。Interceptor是针对Controller接口以及可以处理request和response对象。
1 HandlerInterceptor接口的定义
我们先来看下HandlerInterceptor接口的定义,定义了三个接口,分别是preHandle、postHandle、afterCompletion。
1 public interface HandlerInterceptor { 2 3 boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 4 throws Exception; 5 6 void postHandle( 7 HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 8 throws Exception; 9 10 void afterCompletion( 11 HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 12 throws Exception; 13 14 }
preHandle是调用Controller之前被调用,当返回false后,会跳过之后的拦截器,并且不会执行所有拦截器的postHandle,并调用返回true的拦截器的afterCompletion方法。
postHandle是调用Controller之后被调用,但是在渲染View页面之前。
afterCompletion是调用完Controller接口,渲染View页面最后调用。返回true的拦截器都会调用该拦截器的afterCompletion方法,顺序相反。
和HandlerInterceptor很相似的要有一个AsyncHandlerInterceptor接口,只是多了个afterConcurrentHandlingStarted个方法,当接口使用了异步的方法的时候调用。
1 public interface AsyncHandlerInterceptor extends HandlerInterceptor { 2 3 void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) 4 throws Exception; 5 6 }
2 HandlerInterceptor接口的定义
2.1 DispatcherServlet里doDispatch主处理逻辑
DispatcherServlet里doDispatch()就是springMVC的处理主要逻辑。因此肯定包含了拦截器的主要处理逻辑
1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 2 try { 3 4 try { 5 //.......省略代码 6 7 //返回HandlerExecutionChain 其中包含了拦截器队列 8 mappedHandler = getHandler(processedRequest); 9 10 //调用拦截器PreHandle方法,若返回false不执行Controller逻辑,并不调用下面的PostHandle方法 11 if (!mappedHandler.applyPreHandle(processedRequest, response)) { 12 return; 13 } 14 15 // 处理Controller层 16 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 17 18 applyDefaultViewName(processedRequest, mv); 19 20 //调用拦截器的PostHandle方法 21 mappedHandler.applyPostHandle(processedRequest, response, mv); 22 } 23 catch (Exception ex) { 24 dispatchException = ex; 25 } 26 27 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 28 } 29 catch (Exception ex) { 30 //抛出异常后都会调用拦截器AfterCompletion方法 31 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); 32 } 33 finally { 34 if (asyncManager.isConcurrentHandlingStarted()) { 35 // Instead of postHandle and afterCompletion 36 if (mappedHandler != null) { 37 //若Controller方法为异步调用,则执行拦截器afterConcurrentHandlingStarted(只有AsyncHandlerInterceptor拦截器才有) 38 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); 39 } 40 } 41 } 42 }
2.2 获取拦截器
1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 2 //返回HandlerExecutionChain 其中包含了拦截器队列 3 mappedHandler = getHandler(processedRequest); 4 } 5 //返回HandlerExecutionChain 6 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 7 8 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); 9 return executionChain; 10 } 11 12 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { 13 HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? 14 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); 15 16 //根据url和拦截器异常的配置url做对比,若符合则加入队列 17 String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); 18 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { 19 if (interceptor instanceof MappedInterceptor) { 20 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; 21 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { 22 chain.addInterceptor(mappedInterceptor.getInterceptor()); 23 } 24 } 25 else { 26 chain.addInterceptor(interceptor); 27 } 28 } 29 return chain; 30 } 31 32 public boolean matches(String lookupPath, PathMatcher pathMatcher) { 33 PathMatcher pathMatcherToUse = (this.pathMatcher != null) ? this.pathMatcher : pathMatcher; 34 if (this.excludePatterns != null) { 35 for (String pattern : this.excludePatterns) { 36 if (pathMatcherToUse.match(pattern, lookupPath)) { 37 return false; 38 } 39 } 40 } 41 if (this.includePatterns == null) { 42 return true; 43 } 44 else { 45 for (String pattern : this.includePatterns) { 46 if (pathMatcherToUse.match(pattern, lookupPath)) { 47 return true; 48 } 49 } 50 return false; 51 } 52 }
上述的拦截器的信息,都来自与下面的配置文件
1 <!-- 拦截器链 --> 2 <mvc:interceptors> 3 4 <mvc:interceptor> 5 <!--拦截器mapping 符合的才会执行拦截器--> 6 <mvc:mapping path="/**"/> 7 <!--在拦截器mapping中除去下面的url --> 8 <mvc:exclude-mapping path="/transactional_test/*"/> 9 <!--执行的拦截器--> 10 <ref bean="apiInterceptor"/> 11 </mvc:interceptor> 12 </mvc:interceptors> 13 14 <bean id="apiInterceptor" class="com.lk.dome.interceptor.ApiInterceptor"/> 15 ---------------------
2.3 处理拦截器
1 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { 2 HandlerInterceptor[] interceptors = getInterceptors(); 3 if (!ObjectUtils.isEmpty(interceptors)) { 4 for (int i = 0; i < interceptors.length; i++) { 5 HandlerInterceptor interceptor = interceptors[i]; 6 //若返回false,则直接执行拦截器的triggerAfterCompletion方法 7 if (!interceptor.preHandle(request, response, this.handler)) { 8 triggerAfterCompletion(request, response, null); 9 //直接返回,在外层的doDispatch逻辑中不执行后面的逻辑 10 return false; 11 } 12 //记录成功执行的拦截器个数 13 this.interceptorIndex = i; 14 } 15 } 16 return true; 17 } 18 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { 19 HandlerInterceptor[] interceptors = getInterceptors(); 20 if (!ObjectUtils.isEmpty(interceptors)) { 21 //拦截器队列从后往前之心,顺序相反 22 for (int i = interceptors.length - 1; i >= 0; i--) { 23 HandlerInterceptor interceptor = interceptors[i]; 24 interceptor.postHandle(request, response, this.handler, mv); 25 } 26 } 27 } 28 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) 29 throws Exception { 30 31 HandlerInterceptor[] interceptors = getInterceptors(); 32 if (!ObjectUtils.isEmpty(interceptors)) { 33 //interceptorIndex为执行成功的拦截器标志 34 for (int i = this.interceptorIndex; i >= 0; i--) { 35 HandlerInterceptor interceptor = interceptors[i]; 36 try { 37 interceptor.afterCompletion(request, response, this.handler, ex); 38 } 39 catch (Throwable ex2) { 40 logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); 41 } 42 } 43 } 44 } 45 //异步方法调用,拦截器必须属于AsyncHandlerInterceptor接口 46 void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) { 47 HandlerInterceptor[] interceptors = getInterceptors(); 48 if (!ObjectUtils.isEmpty(interceptors)) { 49 for (int i = interceptors.length - 1; i >= 0; i--) { 50 if (interceptors[i] instanceof AsyncHandlerInterceptor) { 51 try { 52 AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i]; 53 asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler); 54 } 55 catch (Throwable ex) { 56 logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex); 57 } 58 } 59 } 60 } 61 }