spring boot拦截器(interceptor)与过滤器(filter)详细教程
1. 概述
1.1 什么是拦截器(interceptor)?
拦截器是 spring mvc 框架的组件,基于 aop(面向切面编程) 实现。它允许在请求处理的不同阶段(如controller方法执行前后)插入自定义逻辑。
1.2 什么是过滤器(filter)?
过滤器是 java servlet规范 定义的组件,作用于所有进入容器的请求(如tomcat)。它可以在请求到达servlet前或响应返回客户端前进行预处理和后处理。
1.3 核心区别
| 特性 | 拦截器(interceptor) | 过滤器(filter) |
|---|---|---|
| 所属框架 | spring mvc | servlet api |
| 作用范围 | 仅spring mvc管理的请求 | 所有请求(包括静态资源) |
| 依赖 | 依赖spring容器 | 依赖servlet容器(如tomcat) |
| 执行时机 | controller方法前后 | servlet处理前后 |
| 获取bean | 支持(通过spring上下文) | 不支持(需通过其他方式注入) |
2. 使用场景
2.1 拦截器的典型应用
- 日志记录:记录请求参数、响应时间。
- 权限验证:检查用户是否登录或拥有权限。
- 事务管理:在controller方法前后开启/提交事务。
- 性能监控:统计接口耗时。
2.2 过滤器的典型应用
- 全局字符编码:统一设置请求/响应的编码(如utf-8)。
- 跨域处理:添加cors响应头。
- xss防御:过滤请求参数中的恶意脚本。
- 请求压缩:对响应内容进行gzip压缩。
3. 实现步骤
3.1 创建拦截器
步骤:
实现 handlerinterceptor 接口,重写以下方法:
prehandle():在controller方法执行前调用。posthandle():在controller方法执行后、视图渲染前调用。aftercompletion():在请求完成后调用(视图渲染后)。
注册拦截器到spring mvc配置。
代码示例:
public class authinterceptor implements handlerinterceptor {
@override
public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) {
// 检查用户是否登录
if (request.getsession().getattribute("user") == null) {
response.sendredirect("/login");
return false; // 中断请求
}
return true;
}
}注册拦截器:
@configuration
public class webmvcconfig implements webmvcconfigurer {
@override
public void addinterceptors(interceptorregistry registry) {
registry.addinterceptor(new authinterceptor())
.addpathpatterns("/**")
.excludepathpatterns("/login", "/static/**");
}
}注册多个拦截器:
@configuration
public class webmvcconfig implements webmvcconfigurer {
@override
public 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) | 显式设置顺序(默认按注册顺序) |
若要手动指定顺序,可添加:
registry.addinterceptor(new loginterceptor()).order(1); registry.addinterceptor(new authinterceptor()).order(2);
3.2 创建过滤器
步骤:
- 实现
javax.servlet.filter接口,重写dofilter方法。 - 注册过滤器到servlet容器(通过注解或配置类)。
代码示例:
@webfilter(urlpatterns = "/*")
public class loggingfilter implements filter {
@override
public void dofilter(servletrequest request, servletresponse response, filterchain chain)
throws ioexception, servletexception {
system.out.println("请求开始: " + ((httpservletrequest) request).getrequesturi());
chain.dofilter(request, response); // 继续执行后续过滤器或servlet
system.out.println("请求结束");
}
}注册过滤器(若未使用@webfilter):
@configuration
public class filterconfig {
@bean
public filterregistrationbean<loggingfilter> loggingfilter() {
filterregistrationbean<loggingfilter> bean = new filterregistrationbean<>();
bean.setfilter(new loggingfilter());
bean.addurlpatterns("/*");
bean.setorder(1); // 设置执行顺序
return bean;
}
}注意: 确保主类添加 @servletcomponentscan 以启用 @webfilter 注解。
4. 执行顺序与流程
4.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容器注入:
public class authinterceptor implements handlerinterceptor {
@autowired
private userservice userservice; // 直接注入
}q3:过滤器中如何修改请求参数?
通过自定义 httpservletrequestwrapper:
public class modifyrequestwrapper extends httpservletrequestwrapper {
// 重写getparameter等方法以修改参数
}
// 在filter中替换request对象
chain.dofilter(new modifyrequestwrapper(request), response);q4:拦截器和过滤器执行时出现异常如何处理?
- 拦截器:在
aftercompletion中处理异常。 - 过滤器:使用
try-catch包裹chain.dofilter()。
q5:如何让某个拦截器全局生效?
使用 addpathpatterns("/**"):
registry.addinterceptor(new loginterceptor())
.addpathpatterns("/**");q6:如何跳过特定拦截器的执行?
在 prehandle 中返回 false:
@override
public boolean prehandle(...) {
if (跳过条件) {
return false; // 后续拦截器和controller不会执行
}
return true;
}q7:拦截器之间如何共享数据?
通过 request.setattribute 传递:
// 在第一个拦截器中存储数据
request.setattribute("key", "value");
// 在后续拦截器中获取
string value = (string) request.getattribute("key");6. 总结
选择拦截器还是过滤器?
- 需要访问spring上下文或controller信息 → 拦截器。
- 需处理所有请求(包括静态资源) → 过滤器。
最佳实践:
- 优先使用拦截器处理业务相关逻辑。
- 使用过滤器处理底层servlet容器的任务(如编码、压缩)。
到此这篇关于spring boot拦截器(interceptor)与过滤器(filter)详细教程的文章就介绍到这了,更多相关spring boot拦截器与过滤器内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论