一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • 基础系列

  • DB系列

  • 搜索系列

  • MQ系列

  • WEB系列

    • Request

    • Response

    • RestTemplate

    • WebClient

    • WebFlux

    • WebSocket

    • Web三剑客

      • 【WEB系列】Spring MVC之Filter基本使用姿势
      • 【WEB系列】过滤器Filter使用指南
      • 【WEB系列】过滤器Filter使用指南扩展篇
      • 【WEB系列】Servlet 注册的四种姿势
      • 【WEB系列】Listener四种注册姿势
      • 【WEB系列】SpringBoot之拦截器Interceptor使用姿势介绍
        • I. 项目搭建
          • 1. 项目依赖
        • II. 拦截器
          • 1. 自定义拦截器
          • 2. 注册与测试
          • 3. 小结
        • III. 不能错过的源码和相关知识点
          • 0. 项目
          • 1. 一灰灰Blog
      • 【WEB系列】拦截器注入Bean的几种姿势
    • 实例

    • 其他

  • 中间件

  • 运维

  • SpringSecurity

  • SpringCloud

  • Spring系列
  • WEB系列
  • Web三剑客
一灰灰
2021-08-04

【WEB系列】SpringBoot之拦截器Interceptor使用姿势介绍

在SpringMVC中,拦截器与Filter两者的应用场景好像差不多,最大的区别可能是前者属于Spring的特产,而后者则是Servlert三剑客中的一个,它们本质的区别在于两者发生的时机不一致

  • Filter: 在执行Servlet#service方法之前,会执行过滤器;执行完毕之后也会经过过滤器
  • Interceptor: 对会话进行拦截,可以在调用Handler方法之前,视图渲染之前,方法返回之前三个时机触发回调

基于上面的触发时间的不同,两者可以做的事情也不尽相同

  • Filter: 操作Request/Response
  • Interceptor: 操作Request/Response/handler/modelAndView/exception

接下来本文将来看一下,在SpringMVC中拦截器的使用姿势

# I. 项目搭建

# 1. 项目依赖

本项目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发

开一个web服务用于测试

<dependencies>
    <!-- 邮件发送的核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
1
2
3
4
5
6
7

# II. 拦截器

# 1. 自定义拦截器

要实现一个自定义拦截器,一般来讲,实现接口HandlerInterceptor即可

@Slf4j
public class SecurityInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 一个简单的安全校验,要求请求头中必须包含 req-name : yihuihui
        String header = request.getHeader("req-name");
        if ("yihuihui".equals(header)) {
            return true;
        }

        log.info("请求头错误: {}", header);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("执行完毕!");
        response.setHeader("res", "postHandler");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("回收");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

这个接口定义了三个方法,分别在不同的时机触发回调

# 1.1 preHandle

在handler方法执行之前(简单理解为Controller提供的服务调用之前)会被触发,如果返回ture,表示拦截通过,可以执行;若果返回false,表示不允许往后走

因此在这里,通常可以用来做安全校验,用户身份处理等操作

特别需要注意的是,无论是拦截器/还是Filter,在使用 Request 中的请求流的时候,要警惕,通常请求参数流的读取是一次性的,如果在这里实现了一个请求参数日志输出,把请求流的数据读出来了,但是又没有写回去,就会导致请求参数丢失了

# 1.2 postHandler

这个是在handler方法执行之后,视图渲染之前被回调,简单来说,我们在这个时候,是可以操作ModelAndView,往里面添加一下信息,并能被视图解析渲染的

当然鉴于现在前后端分离的趋势,这个实际上用得也不多了

# 1.3 afterCompletion

顾名思义,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行。此方法主要用来进行资源清理

# 2. 注册与测试

接下来让我们自定义的拦截器生效

实现WebMvcConfigurer接口,重写addInterceptors方法,实现拦截器注册

@RestController
@SpringBootApplication
public class Application implements WebMvcConfigurer {
  
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/**");
    }
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
    
    @GetMapping(path = "show")
    public String show() {
        return UUID.randomUUID().toString();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3. 小结

本文补齐了之前遗漏的SpringMVC拦截器的知识点,从使用来看,比较简单,需要注意的知识点,无非就是拦截器的三个时机

  • preHander: controller方法执行前触发,返回ture/false, ture表示通过
  • postHandler: controller执行后,视图渲染前
  • afterCompletion: 执行完毕之后触发

其次,相较于filter而言, 拦截器除了操作requset/response之外,还可以操作handler/modelAndView/exception

# III. 不能错过的源码和相关知识点

# 0. 项目

  • 工程:https://github.com/liuyueyi/spring-boot-demo (opens new window)
  • 源码:https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/213-web-interceptor (opens new window)

# 1. 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

  • 一灰灰Blog个人博客 https://blog.hhui.top (opens new window)
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top (opens new window)

一灰灰blog

编辑 (opens new window)
#Interceptor
上次更新: 2021/10/15, 19:56:22
【WEB系列】Listener四种注册姿势
【WEB系列】拦截器注入Bean的几种姿势

← 【WEB系列】Listener四种注册姿势 【WEB系列】拦截器注入Bean的几种姿势→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×