在Spring Boot应用中,拦截器(Interceptor)和过滤器(Filter)是两种常用的组件,用于处理请求和响应的生命周期。拦截器主要用于处理控制器(Controller)之前或之后的逻辑,而过滤器则用于处理请求和响应的预处理和后处理。理解和掌握拦截器和过滤器的使用方法,对于构建高效、安全的Web应用至关重要。本文将详细介绍Spring Boot中的拦截器和过滤器的原理、配置和应用场景,帮助读者更好地使用这两个组件。
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中的拦截器和过滤器的原理、配置和应用场景。通过本文的学习,读者不仅掌握了拦截器和过滤器的基本概念和使用方法,还学会了如何在实际项目中应用这两个组件,提升Web应用的性能和安全性。希望本文的内容对你有所帮助,期待你在实际项目中应用这些知识,创造出更加优秀的Spring Boot应用。
本文来源于#蹦跑的蜗牛,由@蜜芽 整理发布。如若内容造成侵权/违法违规/事实不符,请联系本站客服处理!
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/3391.html




















