Spring 过滤器(Filter)和过滤器链(Filter Chain)完整示例,包含多个过滤器和Filter 生命周期
Spring 过滤器链(Filter Chain)完整示例
核心目标
展示 多个 Filter 组成过滤器链的完整实现,包含 init()
、doFilter()
、destroy()
全生命周期方法,以及如何通过 FilterRegistrationBean
控制执行顺序。
代码结构
- Filter 1:记录请求时间(
TimingFilter
)。 - Filter 2:跨域处理(
CorsFilter
)。 - Filter 链配置:通过
FilterRegistrationBean
控制顺序。 - 测试 Controller:验证过滤器链执行流程。
完整代码示例
1. Filter 1:记录请求时间
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter // 可选注解(需配合 @ServletComponentScan)
public class TimingFilter implements Filter {
private long startTime; // 记录请求开始时间
// 初始化方法(Filter 容器启动时调用一次)
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("TimingFilter 初始化完成");
// 可读取 Filter 配置参数(如 filterConfig.getInitParameter("key"))
}
// 核心过滤方法(每个请求触发一次)
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
startTime = System.currentTimeMillis();
System.out.println("TimingFilter 前置处理开始");
// 继续 Filter 链或 Controller
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
System.out.println("TimingFilter 后置处理,总耗时:" + (endTime - startTime) + "ms");
}
// 销毁方法(应用关闭时调用一次)
@Override
public void destroy() {
System.out.println("TimingFilter 销毁");
}
}
2. Filter 2:跨域处理
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
@WebFilter
public class CorsFilter implements Filter {
// 初始化方法(Filter 容器启动时调用一次)
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CorsFilter 初始化完成");
}
// 核心过滤方法(每个请求触发一次)
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
System.out.println("CorsFilter 前置处理");
chain.doFilter(request, response); // 继续后续处理
System.out.println("CorsFilter 后置处理");
}
// 销毁方法(应用关闭时调用一次)
@Override
public void destroy() {
System.out.println("CorsFilter 销毁");
}
}
3. Filter 链配置类
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
// 注册 TimingFilter(顺序1)
@Bean
public FilterRegistrationBean<TimingFilter> timingFilterRegistration() {
FilterRegistrationBean<TimingFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new TimingFilter());
registration.addUrlPatterns("/*"); // 拦截所有路径
registration.setOrder(1); // 优先级最高(数值越小优先级越高)
return registration;
}
// 注册 CorsFilter(顺序2)
@Bean
public FilterRegistrationBean<CorsFilter> corsFilterRegistration() {
FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CorsFilter());
registration.addUrlPatterns("/*");
registration.setOrder(2); // 优先级次之
return registration;
}
}
4. 测试 Controller
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
System.out.println("Controller 方法执行");
return "Hello from Controller!";
}
}
5. 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
执行流程与输出结果
访问 /test
接口时,控制台输出如下:
TimingFilter 初始化完成
CorsFilter 初始化完成
// 请求到达时:
TimingFilter 前置处理开始
CorsFilter 前置处理
Controller 方法执行
CorsFilter 后置处理
TimingFilter 后置处理,总耗时:Xms
// 应用关闭时:
CorsFilter 销毁
TimingFilter 销毁
关键流程说明
-
Filter 链执行顺序:
- 初始化阶段:所有 Filter 的
init()
按注册顺序执行(先TimingFilter
再CorsFilter
)。 - 请求处理阶段:
- 前置处理:按
setOrder()
顺序执行(TimingFilter
先于CorsFilter
)。 - 后置处理:按逆序执行(
CorsFilter
先后置,再TimingFilter
后置)。
- 前置处理:按
- 销毁阶段:按初始化顺序的逆序执行(先销毁
CorsFilter
再TimingFilter
)。
- 初始化阶段:所有 Filter 的
-
执行流程图:
请求到达 → ├─ TimingFilter.doFilter() → │ ├─ 前置处理 → │ │ └─ 调用 chain.doFilter() → │ │ ├─ CorsFilter.doFilter() → │ │ │ ├─ 前置处理 → │ │ │ │ └─ 调用 chain.doFilter() → Controller → │ │ │ └─ 后置处理 → │ │ └─ 返回到 TimingFilter → │ └─ 后置处理(计算总耗时) → └─ 响应返回
代码注释详解
-
TimingFilter
:init()
:初始化时打印日志,可读取配置参数。doFilter()
:记录请求开始时间,调用chain.doFilter()
继续链,后置处理计算耗时。destroy()
:释放资源(如关闭数据库连接)。
-
CorsFilter
:init()
:初始化时打印日志。doFilter()
:设置 CORS 头,调用chain.doFilter()
继续链。destroy()
:清理资源。
-
FilterRegistrationBean
:setOrder(1)
:确保TimingFilter
先于CorsFilter
执行。addUrlPatterns("/*")
:拦截所有请求路径。
总结表格
Filter 名称 | 功能 | 执行顺序 | 关键方法 | 生命周期 |
---|---|---|---|---|
TimingFilter | 记录请求处理总耗时 | 1(优先级最高) | init() : 初始化计时器 → doFilter() : 记录开始/结束时间 → destroy() : 无特殊操作 | 初始化时记录启动 → 请求时计算耗时 → 关闭时销毁 Filter 实例 |
CorsFilter | 设置跨域响应头(CORS) | 2(次之) | init() : 初始化 → doFilter() : 设置响应头 → destroy() : 无特殊操作 | 初始化时准备 CORS 配置 → 请求时设置响应头 → 关闭时销毁 Filter 实例 |
关键点总结
-
Filter 链顺序控制:
- 通过
FilterRegistrationBean.setOrder()
设置优先级(数值越小优先级越高)。 - 若未设置
setOrder()
,默认按注册顺序执行。
- 通过
-
Filter 生命周期:
init()
:Servlet 容器启动时调用一次,用于初始化资源。doFilter()
:每个请求触发一次,处理请求/响应。destroy()
:应用关闭时调用一次,用于释放资源。
-
典型应用场景:
- 日志记录:记录请求时间、路径、参数。
- 安全验证:检查 Token、IP 白名单。
- 性能监控:统计接口响应时间。
常见问题
-
如何动态调整 Filter 顺序?
- 修改
FilterRegistrationBean.setOrder()
的数值,无需重启应用即可生效。
- 修改
-
后置处理未执行怎么办?
- 确保
doFilter()
方法中调用了chain.doFilter()
,否则链无法继续。
- 确保
-
如何排除特定路径?
- 在
FilterRegistrationBean
中设置excludeUrlPatterns()
,或在 Filter 内部逻辑中判断路径。
- 在