当前位置:首页 > 学海无涯 > 正文内容

Spring Boot 过滤器入门:从概念到实战配置

清羽天1个月前 (09-15)学海无涯5


在 Web 开发中,过滤器(Filter)是处理 HTTP 请求和响应的重要组件,它能在请求到达控制器前、响应返回客户端前进行拦截和处理。比如日志记录、权限验证、字符编码转换等场景,都离不开过滤器的身影。本文将带大家从零开始,掌握 Spring Boot 中过滤器的入门知识和完整设置流程。

一、过滤器基础:你需要知道的核心概念

1. 过滤器的作用

过滤器本质是一个实现了javax.servlet.Filter接口的 Java 类,它工作在Servlet 容器层面,生命周期由容器管理,主要功能包括:
  • 请求拦截:在请求到达 Controller 前,修改请求参数、头部信息,或直接拒绝请求(如未登录用户拦截);

  • 响应处理:在响应返回客户端前,修改响应内容、设置 Cookie 或响应头(如统一设置跨域头);

  • 通用处理:全局日志记录(记录请求 URL、耗时)、统一字符编码(防止乱码)等。

2. 过滤器的生命周期

Spring Boot 中过滤器的生命周期与 Servlet 容器一致,分为 3 个阶段:
  1. 初始化(init):容器启动时调用init(FilterConfig),初始化过滤器配置(如读取参数),仅执行一次;

  1. 拦截处理(doFilter):每次请求匹配时调用,核心逻辑所在,通过FilterChain传递请求(chain.doFilter(request, response));

  1. 销毁(destroy):容器关闭时调用destroy(),释放资源(如关闭日志流),仅执行一次。

二、Spring Boot 过滤器实战:3 种创建与配置方式

Spring Boot 简化了传统 Java Web 中过滤器的配置(无需web.xml),主流有注解驱动Java 配置类@Component 扫描三种方式,下面逐一讲解。

方式 1:@Component + @WebFilter(最简单,适合单过滤器)

这种方式通过注解自动注册过滤器,无需额外配置,适合单个过滤器的场景。

步骤 1:创建过滤器类

新建LogFilter类,实现Filter接口,添加@Component(让 Spring 扫描)和@WebFilter(指定拦截路径):
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:启动类添加注解

在 Spring Boot 启动类上添加@ServletComponentScan,开启 Servlet 组件扫描(否则@WebFilter不生效):
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);}}

测试效果

启动项目后,访问任意接口(如http://localhost:8080/hello),控制台会输出:
LogFilter初始化...请求URL:/hello,开始时间:1694567890123请求耗时:15ms

方式 2:Java 配置类(推荐,支持多过滤器排序)

当项目中有多个过滤器时,@WebFilter无法指定执行顺序(顺序由类名首字母决定),此时推荐用FilterRegistrationBean配置,手动控制过滤器顺序。

步骤 1:创建多个过滤器

新建LogFilter(日志记录)和AuthFilter(权限验证),不添加@Component@WebFilter(避免自动注册):
// 日志过滤器(同上,省略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:创建配置类注册过滤器

新建FilterConfig类,通过FilterRegistrationBean注册过滤器,并设置拦截路径执行顺序(order 值越小,优先级越高):
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;}}

测试多过滤器顺序

访问http://localhost:8080/api/user(携带空 token),控制台输出顺序如下(验证 LogFilter 先执行):
LogFilter:开始记录日志...AuthFilter:无token,拒绝访问!LogFilter:日志记录结束...

方式 3:@Component + @Order(仅适合全局拦截,不推荐)

若过滤器需要拦截所有请求(/*),可直接用@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. 如何排除特定路径不被拦截?

通过FilterRegistrationBean的addInitParameter()添加排除路径,再在过滤器中判断:
// 配置类中添加排除路径参数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;}// 其他逻辑...}

四、总结

本文讲解了 Spring Boot 过滤器的核心概念、3 种创建配置方式及常见问题:
  1. 简单场景:用@Component + @WebFilter + @ServletComponentScan,快速实现单过滤器;

  1. 复杂场景:用FilterRegistrationBean配置多过滤器,灵活控制拦截路径和执行顺序;

  1. 避免坑点:不推荐用@Component + @Order,因其无法自定义拦截路径。

过滤器是 Spring BootWeb 开发的基础组件,掌握它能帮你实现全局通用功能(如日志、权限),后续可结合 Spring Security、Shiro 等框架进一步深化权限控制。动手试试文中的案例,感受过滤器的实际作用吧!


分享给朋友:

“Spring Boot 过滤器入门:从概念到实战配置” 的相关文章

Linux 忘记密码解决方法

Linux 忘记密码解决方法

很多朋友经常会忘记Linux系统的root密码,linux系统忘记root密码的情况该怎么办呢?重新安装系统吗?当然不用!进入单用户模式更改一下root密码即可。步骤如下:重启linux系统3 秒之内要按一下回车,出现如下界面然后输入e在 第二行最后边输入 single...

Linux常用命令大全

Linux常用命令大全

Linux是开发与运维工作中不可或缺的工具,掌握常用命令能显著提升效率。本篇整理了一些高频使用的命令,覆盖文件操作、系统监控、网络调试等核心场景,适合入门学习或作为日常参考使用。以下是一些常用的Linux命令:1. ls:列出当前目录中的文件和子目录ls2. pwd:显示当前工作目录的路径pwd3....

Spring Boot 配置 Redis 入门指南:从环境搭建到实战操作

Spring Boot 配置 Redis 入门指南:从环境搭建到实战操作**Redis 作为一款高性能的键值对存储数据库,在缓存、会话存储、分布式锁等场景中应用广泛。而 Spring Boot 凭借其 “约定优于配置” 的特性,能极大简化 Redis 的集成流程。本文将从零基础出发,带大家一步步完成...

Spring Boot 实现 MySQL 数据多选删除功能详解

在实际的 Web 开发中,数据删除是常见操作,而多选删除能极大提升用户操作效率,比如批量删除商品、订单、用户信息等场景。本文将基于 Spring Boot 框架,结合 MySQL 数据库,从需求分析到代码实现,完整讲解多选删除功能的开发过程,包含前端页面交互、后端接口设计、数据库操作及异常处理,适合...