Spring Boot 过滤器入门:从概念到实战配置
一、过滤器基础:你需要知道的核心概念
1. 过滤器的作用
请求拦截:在请求到达 Controller 前,修改请求参数、头部信息,或直接拒绝请求(如未登录用户拦截);
响应处理:在响应返回客户端前,修改响应内容、设置 Cookie 或响应头(如统一设置跨域头);
通用处理:全局日志记录(记录请求 URL、耗时)、统一字符编码(防止乱码)等。
2. 过滤器的生命周期
初始化(init):容器启动时调用init(FilterConfig),初始化过滤器配置(如读取参数),仅执行一次;
拦截处理(doFilter):每次请求匹配时调用,核心逻辑所在,通过FilterChain传递请求(chain.doFilter(request, response));
销毁(destroy):容器关闭时调用destroy(),释放资源(如关闭日志流),仅执行一次。
二、Spring Boot 过滤器实战:3 种创建与配置方式
方式 1:@Component + @WebFilter(最简单,适合单过滤器)
步骤 1:创建过滤器类
import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import java.io.IOException;// 标记为Spring组件,自动注入容器@Component// 配置拦截路径:/* 表示拦截所有请求@WebFilter(urlPatterns = "/*", filterName = "logFilter")public class LogFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);// 初始化:容器启动时执行一次@Overridepublic void init(FilterConfig filterConfig) throws ServletException {logger.info("LogFilter初始化...");}// 核心拦截逻辑:每次请求匹配时执行@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 1. 处理请求前:记录请求信息long startTime = System.currentTimeMillis();logger.info("请求URL:{},开始时间:{}",((javax.servlet.http.HttpServletRequest) request).getRequestURI(),startTime);// 2. 放行请求:让请求继续流向Controller(必须调用,否则请求会被拦截)chain.doFilter(request, response);// 3. 处理响应后:记录耗时long endTime = System.currentTimeMillis();logger.info("请求耗时:{}ms", endTime - startTime);}// 销毁:容器关闭时执行一次@Overridepublic void destroy() {logger.info("LogFilter销毁...");}}步骤 2:启动类添加注解
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication// 扫描Servlet组件(Filter、Servlet、Listener)@ServletComponentScanpublic class FilterDemoApplication {public static void main(String[] args) {SpringApplication.run(FilterDemoApplication.class, args);}}测试效果
LogFilter初始化...请求URL:/hello,开始时间:1694567890123请求耗时:15ms
方式 2:Java 配置类(推荐,支持多过滤器排序)
步骤 1:创建多个过滤器
// 日志过滤器(同上,省略init和destroy,核心看doFilter)public class LogFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {logger.info("LogFilter:开始记录日志...");chain.doFilter(request, response);logger.info("LogFilter:日志记录结束...");}}// 权限过滤器:拦截需要登录的请求public class AuthFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(AuthFilter.class);@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {javax.servlet.http.HttpServletRequest httpRequest = (javax.servlet.http.HttpServletRequest) request;String token = httpRequest.getHeader("token");// 模拟权限验证:无token则拦截,返回401if (token == null || token.isEmpty()) {logger.warn("AuthFilter:无token,拒绝访问!");((javax.servlet.http.HttpServletResponse) response).setStatus(401);return;}// 有权限,放行logger.info("AuthFilter:token验证通过,放行请求...");chain.doFilter(request, response);}}步骤 2:创建配置类注册过滤器
import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class FilterConfig {// 注册LogFilter@Beanpublic FilterRegistrationBean<LogFilter> logFilterRegistration() {FilterRegistrationBean<LogFilter> registrationBean = new FilterRegistrationBean<>();// 设置过滤器实例registrationBean.setFilter(new LogFilter());// 设置拦截路径:/* 拦截所有请求registrationBean.addUrlPatterns("/*");// 设置过滤器名称registrationBean.setName("logFilter");// 设置执行顺序:1(优先级高于AuthFilter)registrationBean.setOrder(1);return registrationBean;}// 注册AuthFilter@Beanpublic FilterRegistrationBean<AuthFilter> authFilterRegistration() {FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new AuthFilter());// 设置拦截路径:/api/* 只拦截API请求registrationBean.addUrlPatterns("/api/*");registrationBean.setName("authFilter");// 设置执行顺序:2(后于LogFilter执行)registrationBean.setOrder(2);return registrationBean;}}测试多过滤器顺序
LogFilter:开始记录日志...AuthFilter:无token,拒绝访问!LogFilter:日志记录结束...
方式 3:@Component + @Order(仅适合全局拦截,不推荐)
import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;import javax.servlet.*;import java.io.IOException;// 注入容器,默认拦截所有请求@Component// 设置执行顺序:1(优先级高)@Order(1)public class GlobalFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("GlobalFilter:拦截所有请求...");chain.doFilter(request, response);}}三、过滤器常见问题与解决方案
1. 过滤器不生效?
启动类是否添加@ServletComponentScan(方式 1 必须);
过滤器是否被正确注入容器(方式 2 需通过FilterRegistrationBean注册,避免漏加@Bean);
拦截路径是否正确(如/api/*只拦截/api下的请求,不包括/hello)。
2. 多过滤器执行顺序错乱?
避免用@WebFilter(无法指定顺序),改用FilterRegistrationBean的setOrder();
@Order注解仅在@Component注入时生效,且只对全局拦截的过滤器有效。
3. 如何排除特定路径不被拦截?
// 配置类中添加排除路径参数registrationBean.addInitParameter("excludedUrls", "/login,/register");// 过滤器doFilter方法中判断是否排除@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {String requestURI = ((javax.servlet.http.HttpServletRequest) request).getRequestURI();String excludedUrls = filterConfig.getInitParameter("excludedUrls");if (excludedUrls.contains(requestURI)) {// 排除路径,直接放行chain.doFilter(request, response);return;}// 其他逻辑...}四、总结
简单场景:用@Component + @WebFilter + @ServletComponentScan,快速实现单过滤器;
复杂场景:用FilterRegistrationBean配置多过滤器,灵活控制拦截路径和执行顺序;
避免坑点:不推荐用@Component + @Order,因其无法自定义拦截路径。

