你所需要知道的 Spring 拦截器

前言

现在很多项目都是基于 spring boot 开发的,而且目前很多公司都做 BS,很难避免和 org.springframework.web.servlet.HandlerInterceptor 打交道。因此,我们需要了解它,以备不时之需。

HandlerInterceptor

我们做鉴权或者要对某个特定的路径要做特殊处理时,常常会实现 HandlerInterceptor 或者继承 HandlerInterceptor 的子类。HandlerInterceptor 的类图关系如下


HandlerInterceptor类图关系

HandlerInterceptor 定义了三个方法:

  • preHandle
    严谨的调用时机可以看源码或者看注释。这里简单地说 preHandle 的调用时机是在调用我们的 controller 接口前。
  • postHandle
    在执行完我们 controller 接口后,在渲染页面前(或者说返回 response 给调用方前)。
  • afterCompletion
    在完成 request 请求后会调用该方法。要注意的是:只有 preHandle 方法成功结束并且返回 true才会执行此方法

HandlerInterceptor 的调用时机

我们都知道拦截器要在注册器上注册才会生效,但是它具体是什么时候被调用的呢?请看下图

处理逻辑

这个流程图我省略了比较多处理逻辑,因为那些都不是这篇文章所关心的了。这里主要看 org.springframework.web.servlet.HandlerInterceptor#preHandleorg.springframework.web.servlet.HandlerInterceptor#afterCompletion 何时被调用;多个拦截器时,spring 是怎么处理的,用了什么设计模式,好处是什么。

源码解析

DispatcherServlet 是 spring mvc 一个很重要的类,我们的请求都是由这个调度器分配到适合的方法处理的。

DispatcherServlet#doDispatch

找到当前请求合适的 handler 执行器后,就会执行下面这个方法


image.png

我们看下这个方法里面实际的处理逻辑


HandlerExecutionChain#applyPreHandle

HandlerExecutionChain#applyPreHandle 返回 false 的话,那么调度器就会终止,所以当我们拦截器返回 false时,就无法请求到我们的接口。

note :显然,这里拦截器采用的是责任链设计模式。

好处如下:

  • 解耦
    责任链模式允许将不同的拦截逻辑分离到不同的拦截器类中。每个拦截器类只需要处理自己关注的逻辑,而不必关心其他拦截器的实现。
  • 灵活配置
    通过责任链模式,可以灵活地配置和管理多个拦截器的执行顺序。Spring 提供了方便的配置方式,可以根据需要增加、删除、或调整拦截器的顺序。spring 允许我们通过 addPathPatterns() 为每个拦截器指定适配特定的请求路径。
  • 扩展性
    责任链模式使得新增或移除拦截器变得非常容易。开发者可以随时添加新的拦截器来处理新的需求,而不需要对现有的拦截器做出任何修改。
  • 条件执行
    一个拦截器不通过,后面的拦截器不用执行,提升性能。

afterCompletion

HandlerExecutionChain#applyPreHandle

这里可以看到当有拦截器返回 false 时,就会调用 triggerAfterCompletion 方法,我们看下里面的代码。


afterCompletion

拦截器是遍历执行的,第一个return true 的拦截器的 afterCompletion 最后执行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容