转自: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 }

转载于:https://www.cnblogs.com/sharpest/p/10416198.html

springMVC之Interceptor拦截器相关推荐

  1. 框架:SpringMVC中Interceptor拦截器的两种实现

    Spring中使用Interceptor拦截器 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证, ...

  2. SpringMVC中使用Interceptor拦截器

    2019独角兽企业重金招聘Python工程师标准>>> SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理. ...

  3. Springmvc中的拦截器interceptor及与过滤器filter的区别

    一.Springmvc中的拦截器概述及与过滤器filter的区别 1).Springmvc中的拦截器interceptor用于对控制器controller进行预处理和后处理的技术; 2).可以定义拦截 ...

  4. 在SpringMVC中使用拦截器(interceptor)拦截CSRF***

    关于什么是CSRF我这里就不多说了,以前转载的一篇文章(PS:https://www.zifangsky.cn/358.html)已经说得很清楚了.这里只是简单介绍如何在SpringMVC中使用拦截器 ...

  5. SpringMVC中的拦截器

    SpringMVC中的拦截器 拦截器的作用 Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理. 用户可以自己定义一些拦截器来实现 ...

  6. spring拦截器覆盖_Spring中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  7. 【Java代码】使用 org.apache.ibatis.plugin.Interceptor 拦截器实现全局 mapper.xml 参数注入(可用于切换数据库实例schema+Demo举例源码)

    1. why   项目没有使用MyBatis,进行数据操作时使用的是jdbc中默认的schema,现在项目要加入多租户,同一个数据库下不同租户使用不同的实例schema,这就要在mapper文件内所有 ...

  8. (转)SpringMVC学习(十二)——SpringMVC中的拦截器

    http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...

  9. 【Java从0到架构师】SpringMVC - 异常处理_拦截器

    异常处理_拦截器 异常处理 简单的异常与页面映射 - SimpleMappingExceptionResolver √自定义异常处理类 - 实现 HandlerExceptionResolver 接口 ...

最新文章

  1. 爬虫进阶教程:极验(GEETEST)验证码破解教程
  2. 2022版全球及中国煤矿机械再制造行业“十四五”发展规划与投资建议报告
  3. 【NLP】新分类!全总结!最新Awesome-SLU-Survey资源库开源!
  4. AI大神贾扬清确认将离开Facebook,加入阿里硅谷研究院
  5. 我的技术家园,吸取精神食粮的天堂
  6. WSS Alert(邮件提醒) 定制
  7. platform_SpringOne Platform 2016回顾
  8. Apache TomEE + JMS。 这从未如此简单。
  9. 关于linux用户权限的理解
  10. 由PPPOE看Linux网络协议栈的实现
  11. 吓坏了!智能锁半夜自己“离奇打开”
  12. 用户注册与登陆(验证和数据库)
  13. 机器学习基础(五十五)—— 核(Kernel Trick)
  14. python学出来能做什么-python学出来能做什么
  15. Oracle SUn
  16. 更新macOS Big Sur系统后,Parallels Desktop打不开怎么办?教你解决方法!
  17. RxBus的使用及解析
  18. 字节跳动小程序平台审核常见被拒情形
  19. C51单片机实现呼吸灯
  20. 那些踩过的declared implicitly的坑

热门文章

  1. linux中的NFS服务器配置及/etc/exports
  2. org manual翻译--3.5.8 更新表格
  3. hdu2716水水哈希
  4. mass Framework event模块 v8
  5. python求1到n的乘积_Python简单实现两个任意字符串乘积的方法示例
  6. 未定义标识符 stringc/c++(20)_20款奔驰G63AMG霸气颜值 运动造型
  7. Nginx —— ngx_http_core_module 模块提供的变量
  8. vue 使用element 菜单与tab页联动
  9. 秀尔算法:破解RSA加密的“不灭神话” --zz
  10. 判断一个数是否是素数(质数)