Spring Boot拦截器(Interceptor)与过滤器(Filter)详细教程

ops/2025/3/1 20:32:56/

Spring Boot拦截器(Interceptor)与过滤器(Filter)详细教程


目录

  1. 概述
    • 什么是拦截器(Interceptor)?
    • 什么是过滤器(Filter)?
    • 两者的核心区别
  2. 使用场景
    • 拦截器的典型应用
    • 过滤器的典型应用
  3. 实现步骤
    • 拦截器的创建与配置
    • 过滤器的创建与配置
  4. 代码示例
    • 自定义拦截器
    • 自定义过滤器
  5. 执行顺序与流程
    • 过滤器、拦截器、Controller的执行顺序
    • 可视化流程图
  6. 常见问题与解决方案
  7. 总结

1. 概述

1.1 什么是拦截器(Interceptor)?

拦截器是 Spring MVC 框架的组件,基于 AOP(面向切面编程) 实现。它允许在请求处理的不同阶段(如Controller方法执行前后)插入自定义逻辑。

1.2 什么是过滤器(Filter)?

过滤器是 Java Servlet规范 定义的组件,作用于所有进入容器的请求(如Tomcat)。它可以在请求到达Servlet前或响应返回客户端前进行预处理和后处理。

1.3 核心区别

特性拦截器(Interceptor)过滤器(Filter)
所属框架Spring MVCServlet API
作用范围仅Spring MVC管理的请求所有请求(包括静态资源)
依赖依赖Spring容器依赖Servlet容器(如Tomcat)
执行时机Controller方法前后Servlet处理前后
获取Bean支持(通过Spring上下文)不支持(需通过其他方式注入)

2. 使用场景

2.1 拦截器的典型应用

  • 日志记录:记录请求参数、响应时间。
  • 权限验证:检查用户是否登录或拥有权限。
  • 事务管理:在Controller方法前后开启/提交事务。
  • 性能监控:统计接口耗时。

2.2 过滤器的典型应用

  • 全局字符编码:统一设置请求/响应的编码(如UTF-8)。
  • 跨域处理:添加CORS响应头。
  • XSS防御:过滤请求参数中的恶意脚本。
  • 请求压缩:对响应内容进行GZIP压缩。

3. 实现步骤

3.1 创建拦截器

步骤:

  1. 实现 HandlerInterceptor 接口,重写以下方法:
    • preHandle():在Controller方法执行前调用。
    • postHandle():在Controller方法执行后、视图渲染前调用。
    • afterCompletion():在请求完成后调用(视图渲染后)。
  2. 注册拦截器到Spring MVC配置。

代码示例:

java">public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 检查用户是否登录if (request.getSession().getAttribute("user") == null) {response.sendRedirect("/login");return false; // 中断请求}return true;}
}

注册拦截器:

java">@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**").excludePathPatterns("/login", "/static/**");}
}

注册多个拦截器:

java">@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 第一个拦截器:日志(优先级高)registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**")       // 拦截所有路径.excludePathPatterns("/static/**"); // 排除静态资源// 第二个拦截器:权限(优先级低)registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**");  // 仅拦截/api路径}
}

关键配置选项

配置方法说明
addPathPatterns("/api")指定拦截的路径(支持Ant风格)
excludePathPatterns("/login")排除特定路径
order(1)显式设置顺序(默认按注册顺序)

若要手动指定顺序,可添加:

java">registry.addInterceptor(new LogInterceptor()).order(1);
registry.addInterceptor(new AuthInterceptor()).order(2);

3.2 创建过滤器

步骤:

  1. 实现 javax.servlet.Filter 接口,重写 doFilter 方法。
  2. 注册过滤器到Servlet容器(通过注解或配置类)。

代码示例:

java">@WebFilter(urlPatterns = "/*")
public class LoggingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("请求开始: " + ((HttpServletRequest) request).getRequestURI());chain.doFilter(request, response); // 继续执行后续过滤器或ServletSystem.out.println("请求结束");}
}

注册过滤器(若未使用@WebFilter):

java">@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<LoggingFilter> loggingFilter() {FilterRegistrationBean<LoggingFilter> bean = new FilterRegistrationBean<>();bean.setFilter(new LoggingFilter());bean.addUrlPatterns("/*");bean.setOrder(1); // 设置执行顺序return bean;}
}

注意: 确保主类添加 @ServletComponentScan 以启用 @WebFilter 注解。


4. 执行顺序与流程

4.1 执行顺序

  1. 过滤器(FilterChain) → 2. 拦截器(preHandle) → 3. Controller方法 → 4. 拦截器(postHandle) → 5. 视图渲染 → 6. 拦截器(afterCompletion) → 7. 过滤器后续处理

4.2 流程图

客户端 → Filter.doFilter() → Interceptor.preHandle()→ Controller → Interceptor.postHandle()→ 视图渲染 → Interceptor.afterCompletion()→ Filter.doFilter()后续处理 → 客户端

5. 常见问题与解决方案

Q1:如何控制多个拦截器/过滤器的执行顺序?

  • 拦截器:通过 registry.addInterceptor() 的顺序决定。
  • 过滤器:通过 FilterRegistrationBean.setOrder() 设置优先级(值越小越先执行)。

Q2:拦截器中如何获取Spring管理的Bean?

直接从Spring容器注入:

java">public class AuthInterceptor implements HandlerInterceptor {@Autowiredprivate UserService userService; // 直接注入
}

Q3:过滤器中如何修改请求参数?

通过自定义 HttpServletRequestWrapper

java">public class ModifyRequestWrapper extends HttpServletRequestWrapper {// 重写getParameter等方法以修改参数
}// 在Filter中替换Request对象
chain.doFilter(new ModifyRequestWrapper(request), response);

Q4:拦截器和过滤器执行时出现异常如何处理?

  • 拦截器:在 afterCompletion 中处理异常。
  • 过滤器:使用 try-catch 包裹 chain.doFilter()

Q5:如何让某个拦截器全局生效?

使用 addPathPatterns("/**")

java">registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**");

Q6:如何跳过特定拦截器的执行?

preHandle 中返回 false

java">@Override
public boolean preHandle(...) {if (跳过条件) {return false; // 后续拦截器和Controller不会执行}return true;
}

Q7:拦截器之间如何共享数据?

通过 request.setAttribute 传递:

java">// 在第一个拦截器中存储数据
request.setAttribute("key", "value");// 在后续拦截器中获取
String value = (String) request.getAttribute("key");

6. 总结

  • 选择拦截器还是过滤器?

    • 需要访问Spring上下文或Controller信息 → 拦截器。
    • 需处理所有请求(包括静态资源) → 过滤器。
  • 最佳实践

    • 优先使用拦截器处理业务相关逻辑。
    • 使用过滤器处理底层Servlet容器的任务(如编码、压缩)。

http://www.ppmy.cn/ops/162321.html

相关文章

DeepSeek能画流程图吗?分享一种我正在使用的DeepSeek画流程图教程

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌​‌‌‌‌​​‍‌​‌​‌‌​​‍‌​​​‌‌‌‌‍‌​‌‌​‌‌‌‍‌‌​​‌​‌​‍‌​​‌‌​‌‌‍‌​​​‌​‌​‍‌​‌‌‌​‌‌‍‌‌​​‌‌‌‌‍‌​‌‌‌​​​‍‌…

Transformer 代码剖析6 - 位置编码 (pytorch实现)

一、位置编码的数学原理与设计思想 1.1 核心公式解析 位置编码采用正弦余弦交替编码方案&#xff1a; P E ( p o s , 2 i ) sin ⁡ ( p o s 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i 1 ) cos ⁡ ( p o s 1000 0 2 i / d m o d e l ) PE_{(pos,2i)} \sin\left(\fra…

Flutter 学习之旅 之 flutter 在 Android 端进行简单的图片裁剪操作

Flutter 学习之旅 之 flutter 在 Android 端进行简单的图片裁剪操作 目录 Flutter 学习之旅 之 flutter 在 Android 端进行简单的图片裁剪操作 一、简单介绍 二、简单介绍 image_cropper 三、安装 image_picker 四、简单案例实现 五、关键代码 一、简单介绍 Flutter 是一…

vue+element ui 实现选择季度组件

1、实现效果 和element ui 选择月份同样的效果&#xff0c;也支持键盘上下左右控制选择季度。 2、页面调用 <ElQuarterPicker v-model"value" placeholder"选择季度"></ElQuarterPicker> 3、组件代码&#xff1a; ElQuarterPicker.vue &l…

华为在不同发展时期的战略选择(节选)

华为在不同发展时期的战略选择&#xff08;节选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 来源&#xff1a;谢宁专著《华为战略管理法&#xff1a;DSTE实战体系》。本文有节选修改。 导言 从目前所取得的成就往回看&#xff0c;华为…

C语言【进阶篇】之指针——涵盖基础、数组与高级概念

目录 &#x1f680;前言&#x1f914;指针是什么&#x1f31f;指针基础&#x1f4af;内存与地址&#x1f4af;指针变量&#x1f4af; 指针类型&#x1f4af;const 修饰指针&#x1f4af;指针运算&#x1f4af;野指针和 assert 断言 &#x1f4bb;数组与指针&#x1f4af;数组名…

深度学习基础--ResNet50V2网络的讲解,ResNet50V2的复现(pytorch)以及用复现的ResNet50做鸟类图像分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 如果说最经典的神经网络&#xff0c;ResNet肯定是一个&#xff0c;从ResNet发布后&#xff0c;作者又进行修改&#xff0c;命名为ResNe50v2&#xff0c…

Cursor+pycharm接入Codeuim(免费版),Tab自动补全功能平替

如题&#xff0c;笔者在Cursor中使用pycharm写python程序&#xff0c;试用期到了Tab自动补全功能就不能用了&#xff0c;安装Codeuim插件可以代替这个功能。步骤如下&#xff1a; 1. 在应用商店中搜索扩展Codeuim&#xff0c;下载安装 2. 安装完成后左下角会弹出提示框&#x…