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

springMVC之Interceptor拦截器的更多相关文章

  1. SpringMvc中Interceptor拦截器用法

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

  2. SpringMVC中使用Interceptor拦截器

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

  3. SpringMVC 中的Interceptor 拦截器

    1.配置拦截器 在springMVC.xml配置文件增加: <mvc:interceptors>  <!-- 日志拦截器 -->  <mvc:interceptor> ...

  4. SpringMVC中使用Interceptor拦截器顺序

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

  5. SpringMVC中的Interceptor拦截器及与Filter区别

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

  6. springmvc中的拦截器interceptor用法

    1.配置拦截器 在springMVC.xml配置文件增加: 1 <mvc:interceptors> 2 <!-- 日志拦截器 --> 3 <mvc:intercepto ...

  7. [转]SpringMVC中使用Interceptor拦截器

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

  8. SpringMVC之七:SpringMVC中使用Interceptor拦截器

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

  9. 9.springMVC中的拦截器

    springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ...

随机推荐

  1. WIFI_认证加密学习_STA_AP_WDS

    2-1.1_15_使用卡1_准备工作及配置内核====================================1.无线网卡连接上路由或AP之后使用上是和有线网卡是一样的,都是socket编程. ...

  2. oracle 与sql serve 获取随机行数的数据

    Oracle 随机获取N条数据    当我们获取数据时,可能会有这样的需求,即每次从表中获取数据时,是随机获取一定的记录,而不是每次都获取一样的数据,这时我们可以采取Oracle内部一些函数,来达到这 ...

  3. JS 网页快捷键设置

    我们希望能用快捷键代替鼠标点击做一些事情,例如一个典型的应用就是论坛上常用的Ctrl + Enter 快捷发帖子.就以Ctrl+Enter快捷发帖子为例,实质上呢,就是通过JS脚本,捕获系统的onke ...

  4. 和为 s 的两个数字(和为 s 的连续正数序列)

    题目 输入一个递增排序的数组和一个数字 s,在数组中查找两个数,得它们的和正好是 s.如果有多对数字的和等于 s,输出任意一对即可 思路 我们先在数组中选择两个数字,如果它们的和等于输入的 s,我们就 ...

  5. 浏览器的自动翻译会影响 JS 逻辑

    有人在 QQ 群里反馈,官方注册后跳转时出现 Bug. 收到群友非常有用的资讯,这是因为浏览器的自动翻译功能引起的. 11:04:21[潜水]Better Command 2017/12/30 11: ...

  6. mac下hbase安装

    出处:https://www.jianshu.com/p/510e1d599123 安装到的路径:/usr/local/Cellar/hbase/1.2.6 linux操作: linux命令 作用 . ...

  7. POJ1179 Polygon

    题目:http://poj.org/problem?id=1179 石子合并的升级版.有负值.但运算符只有 + 和 * . 考虑负值对原做法正确性的影响:之所以仅记录最大值可能不对,是因为有可能负数 ...

  8. 二、Jmeter录制脚本过程及Could not create script recorder报错、您的连接不是私密连接报错

    两个报错:Could not create script recorder报错和您的连接不是私密连接报错 1.录制过程 * 打开jmeter * 点击Templated,选择Recoding模版 * ...

  9. ORA-01919: role 'OLAPI_TRACE_USER' does not exist

    我在用数据泵导入数据的时候报的错 TEST_USER1@ORCL> conn / as sysdbaSYS@ORCL> grant plustrace to TEST_USER1; gra ...

  10. 什么是JavaBean、bean? 什么是POJO、PO、DTO、VO、BO ? 什么是EJB、EntityBean?

    什么是JavaBean.bean?  什么是POJO.PO.DTO.VO.BO ?  什么是EJB.EntityBean?   前言:   在Java开发中经常遇到这些概念问题,有的可能理解混淆,有的 ...