【Spring Boot 过滤器】
文章目录
- 前言
- 一、什么是过滤器 Filter?
- 二、Spring Boot 中使用 Filter 的方式
- 1. 使用 `@Component` 注解
- 2. 使用 `FilterRegistrationBean` 显式注册
- 三、自定义过滤器示例
- 1. 引入必要依赖
- 2. 创建一个自定义 Filter
- 3. 使用 FilterRegistrationBean 显式注册
- 四、多个 Filter 的执行顺序
- 五、Filter 与 Interceptor 和 AOP 的区别
- 六、过滤器实现登录校验
- 总结
前言
在Web开发中,我们常常需要对请求做一些统一的处理,例如:请求日志记录、权限验证、跨域处理等。Spring Boot 中除了可以使用拦截器(Interceptor)和AOP,还可以使用过滤器(Filter)。
一、什么是过滤器 Filter?
Filter 是 Servlet 规范中的一个组件,用于在请求到达 Servlet 之前或响应返回客户端之前进行预处理或后处理。它可以用来实现:
- 请求日志记录
- 用户认证与权限检查
- 参数过滤与包装
- 编码设置
- 防止 XSS 攻击等
它的核心接口是 javax.servlet.Filter
。
二、Spring Boot 中使用 Filter 的方式
在 Spring Boot 中,有两种方式注册 Filter:
1. 使用 @Component
注解
直接在自定义的 Filter 类上加上 @Component
注解即可自动注册到 Spring 容器中。
2. 使用 FilterRegistrationBean
显式注册
可以通过创建一个 FilterRegistrationBean
的 Bean,来手动注册过滤器,并设置过滤路径、顺序等信息。
三、自定义过滤器示例
1. 引入必要依赖
Spring Boot 的 Web 项目只需要依赖如下 starter(通常已包含在创建项目时):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 创建一个自定义 Filter
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class MyLogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyLogFilter 初始化...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
System.out.println("请求路径:" + req.getRequestURI());
// 放行请求
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("MyLogFilter 销毁...");
}
}
运行项目访问接口时,你会在控制台看到日志输出。
3. 使用 FilterRegistrationBean 显式注册
如果你想更细粒度地控制 Filter,例如:设置过滤路径或顺序,可以使用如下方式:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyLogFilter> registerLogFilter() {
FilterRegistrationBean<MyLogFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyLogFilter());
registrationBean.addUrlPatterns("/api/*"); // 指定过滤路径
registrationBean.setOrder(1); // 设置执行顺序,值越小优先级越高
return registrationBean;
}
}
四、多个 Filter 的执行顺序
如果你注册了多个 Filter,执行顺序取决于:
- 使用
@Component
的方式时,默认顺序不确定(但可以使用@Order
注解控制顺序) - 使用
FilterRegistrationBean
的方式时,可以通过setOrder()
方法设置优先级
示例:
@Component
@Order(2)
public class SecondFilter implements Filter {
// ...
}
五、Filter 与 Interceptor 和 AOP 的区别
特性/维度 | Filter | Interceptor(拦截器) | AOP(切面) |
---|---|---|---|
所属层 | Servlet 规范 | Spring MVC | Spring AOP |
作用对象 | HttpServletRequest | Controller 方法 | 任意 Bean 方法 |
控制范围 | Servlet 全请求生命周期 | 请求到达 Controller 前后 | 方法执行前后 |
应用场景 | 日志、权限、跨域、编码处理 | 权限校验、接口日志等 | 事务、缓存、日志等通用逻辑 |
六、过滤器实现登录校验
拦截所有 /admin/**
路径下的请求,如果请求头中没有携带 token
参数,则返回 401。
@Component
@Order(1)
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String uri = req.getRequestURI();
if (uri.startsWith("/admin/")) {
String token = req.getHeader("token");
if (token == null || token.isEmpty()) {
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.getWriter().write("401 Unauthorized");
return;
}
}
chain.doFilter(request, response);
}
}
访问 /admin/**
路径时,必须在请求头中携带 token。
总结
- Filter 的概念和作用
- 使用
@Component
和FilterRegistrationBean
的两种注册方式 - 多个过滤器的顺序控制
- Filter 与 Interceptor、AOP 的区别
- 实际案例:请求日志、登录校验