springMVC之Interceptor拦截器
转自:https://blog.csdn.net/qq_25673113/article/details/79153547
Interceptor拦截器用于拦截Controller层接口,表现形式有点像Spring的AOP,但是AOP是针对单一的方法。Interceptor是针对Controller接口以及可以处理request和response对象。
1 HandlerInterceptor接口的定义
我们先来看下HandlerInterceptor接口的定义,定义了三个接口,分别是preHandle、postHandle、afterCompletion。
 public interface HandlerInterceptor {
     boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception;
     void postHandle(
             HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
             throws Exception;
     void afterCompletion(
             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
             throws Exception;
 }
preHandle是调用Controller之前被调用,当返回false后,会跳过之后的拦截器,并且不会执行所有拦截器的postHandle,并调用返回true的拦截器的afterCompletion方法。 
postHandle是调用Controller之后被调用,但是在渲染View页面之前。 
afterCompletion是调用完Controller接口,渲染View页面最后调用。返回true的拦截器都会调用该拦截器的afterCompletion方法,顺序相反。
和HandlerInterceptor很相似的要有一个AsyncHandlerInterceptor接口,只是多了个afterConcurrentHandlingStarted个方法,当接口使用了异步的方法的时候调用。
 public interface AsyncHandlerInterceptor extends HandlerInterceptor {
     void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception;
 }
2 HandlerInterceptor接口的定义
2.1 DispatcherServlet里doDispatch主处理逻辑
DispatcherServlet里doDispatch()就是springMVC的处理主要逻辑。因此肯定包含了拦截器的主要处理逻辑
 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
         try {
             try {
                 //.......省略代码
                 //返回HandlerExecutionChain  其中包含了拦截器队列
                 mappedHandler = getHandler(processedRequest);
                 //调用拦截器PreHandle方法,若返回false不执行Controller逻辑,并不调用下面的PostHandle方法
                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                     return;
                 }
                 // 处理Controller层
                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                 applyDefaultViewName(processedRequest, mv);
                 //调用拦截器的PostHandle方法
                 mappedHandler.applyPostHandle(processedRequest, response, mv);
             }
             catch (Exception ex) {
                 dispatchException = ex;
             }
             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
         }
         catch (Exception ex) {
             //抛出异常后都会调用拦截器AfterCompletion方法
             triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
         }
         finally {
             if (asyncManager.isConcurrentHandlingStarted()) {
                 // Instead of postHandle and afterCompletion
                 if (mappedHandler != null) {
                     //若Controller方法为异步调用,则执行拦截器afterConcurrentHandlingStarted(只有AsyncHandlerInterceptor拦截器才有)
                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                 }
             }
         }
     }
2.2 获取拦截器
 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     //返回HandlerExecutionChain  其中包含了拦截器队列
     mappedHandler = getHandler(processedRequest);
 }
 //返回HandlerExecutionChain
 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
     return executionChain;
 }
 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
         HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
         //根据url和拦截器异常的配置url做对比,若符合则加入队列
         String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
         for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
             if (interceptor instanceof MappedInterceptor) {
                 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                     chain.addInterceptor(mappedInterceptor.getInterceptor());
                 }
             }
             else {
                 chain.addInterceptor(interceptor);
             }
         }
         return chain;
 }
 public boolean matches(String lookupPath, PathMatcher pathMatcher) {
         PathMatcher pathMatcherToUse = (this.pathMatcher != null) ? this.pathMatcher : pathMatcher;
         if (this.excludePatterns != null) {
             for (String pattern : this.excludePatterns) {
                 if (pathMatcherToUse.match(pattern, lookupPath)) {
                     return false;
                 }
             }
         }
         if (this.includePatterns == null) {
             return true;
         }
         else {
             for (String pattern : this.includePatterns) {
                 if (pathMatcherToUse.match(pattern, lookupPath)) {
                     return true;
                 }
             }
             return false;
         }
 }
上述的拦截器的信息,都来自与下面的配置文件
<!-- 拦截器链 -->
<mvc:interceptors> <mvc:interceptor>
<!--拦截器mapping 符合的才会执行拦截器-->
<mvc:mapping path="/**"/>
<!--在拦截器mapping中除去下面的url -->
<mvc:exclude-mapping path="/transactional_test/*"/>
<!--执行的拦截器-->
<ref bean="apiInterceptor"/>
</mvc:interceptor>
</mvc:interceptors> <bean id="apiInterceptor" class="com.lk.dome.interceptor.ApiInterceptor"/>
---------------------
2.3 处理拦截器
 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];
                 //若返回false,则直接执行拦截器的triggerAfterCompletion方法
                 if (!interceptor.preHandle(request, response, this.handler)) {
                     triggerAfterCompletion(request, response, null);
                     //直接返回,在外层的doDispatch逻辑中不执行后面的逻辑
                     return false;
                 }
                 //记录成功执行的拦截器个数
                 this.interceptorIndex = i;
             }
         }
         return true;
 }
 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);
             }
         }
 }
 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
             throws Exception {
         HandlerInterceptor[] interceptors = getInterceptors();
         if (!ObjectUtils.isEmpty(interceptors)) {
             //interceptorIndex为执行成功的拦截器标志
             for (int i = this.interceptorIndex; i >= 0; i--) {
                 HandlerInterceptor interceptor = interceptors[i];
                 try {
                     interceptor.afterCompletion(request, response, this.handler, ex);
                 }
                 catch (Throwable ex2) {
                     logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
                 }
             }
         }
 }
 //异步方法调用,拦截器必须属于AsyncHandlerInterceptor接口
 void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
         HandlerInterceptor[] interceptors = getInterceptors();
         if (!ObjectUtils.isEmpty(interceptors)) {
             for (int i = interceptors.length - 1; i >= 0; i--) {
                 if (interceptors[i] instanceof AsyncHandlerInterceptor) {
                     try {
                         AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
                         asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
                     }
                     catch (Throwable ex) {
                         logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
                     }
                 }
             }
         }
 }
springMVC之Interceptor拦截器的更多相关文章
- SpringMvc中Interceptor拦截器用法
		SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆等. 一. 使用场景 1 ... 
- SpringMVC中使用Interceptor拦截器
		SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ... 
- SpringMVC 中的Interceptor 拦截器
		1.配置拦截器 在springMVC.xml配置文件增加: <mvc:interceptors> <!-- 日志拦截器 --> <mvc:interceptor> ... 
- SpringMVC中使用Interceptor拦截器顺序
		一.简介 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验 证,或者是来判断用户是否登陆,或者是像1 ... 
- SpringMVC中的Interceptor拦截器及与Filter区别
		SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ... 
- springmvc中的拦截器interceptor用法
		1.配置拦截器 在springMVC.xml配置文件增加: 1 <mvc:interceptors> 2 <!-- 日志拦截器 --> 3 <mvc:intercepto ... 
- [转]SpringMVC中使用Interceptor拦截器
		SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ... 
- SpringMVC之七:SpringMVC中使用Interceptor拦截器
		SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ... 
- 9.springMVC中的拦截器
		springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ... 
随机推荐
- hdu2098 分拆素数和 素数筛
			将一个偶数拆成两个素数的和,欧拉筛暴力 #include<stdio.h> #include<string.h> #define N 10001 ]; ]; ,j; void ... 
- Sublime Text3 使用
			注: 1.绿色版的某些插件有问题,导致某些插件无法使用,而且无法删除和安装,需要删除Data/Cache目录,重新安装无法使用的插件 2.绿色版无法编译python,可使用安装版安装sublime后, ... 
- vue组件独享守卫钩子函数参数详解(beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave)
			一样的和前面路由钩子类似的步骤 首先在demo下面的components下面新建一个test.vue组件 test组件代码 <template> <div class="t ... 
- 【HAOI2014】贴海报
			弱省中的弱省……原题: Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论.为了统一管理,城市委员会为选民准备了一个张贴海报的electoral墙.张贴规则如下:1 ... 
- [团队项目]SCRUM项目6.0 7.0
			6.0----------------------------------------------------- sprint演示 1.坚持所有的sprint都结束于演示. 团队的成果得到认可,会感觉 ... 
- CSS3 Flexbox轻巧实现元素的水平居中和垂直居中(转)
			CSS3 Flexbox轻松实现元素的水平居中和垂直居中 网上有很多关于Flex的教程,对于Flex的叫法也不一,有的叫Flexbox,有的叫Flex,其实这两种叫法都没有错,只是Flexbox旧一点 ... 
- python之 利用字典与函数实现switch case功能
			Python不像C/C++,Java等有switch-case的语法.不过其这个功能,比如用Dictionary以及lambda匿名函数特性来替代实现. 字典+函数实现switch模式下的四则运算:( ... 
- js 数组方法比较
			js 数组方法比较 table th:first-of-type { width: 80px; } table th:nth-of-type(2) { width: 120px; } table th ... 
- java 中的 hashcode
			在Java的Object类中有一个方法: public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没 ... 
- Navicat导出opencart2.3数据字典
			步骤请参考:http://blog.csdn.net/maquealone/article/details/60764420 运行SQL: 备注:opcml是数据库名称. select TABLE ... 
