Spring Boot 实现过滤器(Filter)三种常用方式

Filter 是 Java Web 原生组件,优先级早于 Interceptor,可拦截所有请求,下面分三种主流实现方式,附完整代码、配置、执行顺序。

一、前置说明

  • 过滤器基于 javax.servlet.Filter(Servlet 规范)
  • Spring Boot 无需手动配置 web.xml注解/注册 Bean 即可生效
  • 执行顺序:Filter → DispatcherServlet → Interceptor → Controller

方式一:注解方式(最简,推荐简单场景)

使用 @WebFilter + 启动类开启 Servlet 注解扫描,零配置

1. 编写自定义过滤器

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

// 拦截所有请求 /*
@WebFilter(filterName = "MyFilter", urlPatterns = "/*")
public class MyFilter implements Filter {

    // 初始化(容器启动执行一次)
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化");
    }

    // 核心拦截逻辑(每次请求都会执行)
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        // 放行前逻辑(前置处理)
        System.out.println("请求地址:" + req.getRequestURI());

        // 放行,执行后续过滤器/接口
        chain.doFilter(request, response);

        // 放行后逻辑(后置处理,响应返回客户端前)
        System.out.println("请求结束");
    }

    // 销毁(容器关闭执行一次)
    @Override
    public void destroy() {
        System.out.println("过滤器销毁");
    }
}

2. 启动类开启注解支持

启动类添加 @ServletComponentScan,扫描 @WebFilter

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan // 关键注解:扫描 Servlet、Filter、Listener
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

优缺点

  • ✅ 简单快捷,适合单过滤器、简单项目
  • 无法手动指定多个过滤器执行顺序

方式二:注册 FilterRegistrationBean(推荐,可控制顺序)

Spring Boot 官方推荐方式,支持排序、指定拦截路径、禁用原生注解,多过滤器首选。

1. 先写过滤器(普通 Java 类,不加 @WebFilter)

java 复制代码
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class OrderFilter1 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("【过滤器1】执行");
        chain.doFilter(request, response);
        System.out.println("【过滤器1】结束");
    }

    @Override
    public void init(FilterConfig filterConfig) {}
    @Override
    public void destroy() {}
}
java 复制代码
public class OrderFilter2 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("【过滤器2】执行");
        chain.doFilter(request, response);
        System.out.println("【过滤器2】结束");
    }

    @Override
    public void init(FilterConfig filterConfig) {}
    @Override
    public void destroy() {}
}

2. 编写配置类,注册过滤器 + 排序

order越小,优先级越高,越先执行

java 复制代码
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<OrderFilter1> filter1() {
        FilterRegistrationBean<OrderFilter1> bean = new FilterRegistrationBean<>();
        bean.setFilter(new OrderFilter1());
        bean.addUrlPatterns("/*"); // 拦截路径
        bean.setOrder(1); // 执行顺序:1 > 2
        return bean;
    }

    @Bean
    public FilterRegistrationBean<OrderFilter2> filter2() {
        FilterRegistrationBean<OrderFilter2> bean = new FilterRegistrationBean<>();
        bean.setFilter(new OrderFilter2());
        bean.addUrlPatterns("/*");
        bean.setOrder(2); // 顺序靠后
        return bean;
    }
}

执行顺序

请求进来:Filter1 → Filter2 → 接口 → Filter2后置 → Filter1后置

常用配置扩展

java 复制代码
// 排除指定路径
bean.addInitParameter("exclusions", "/login,/static/*");
// 设置过滤器名称
bean.setName("customFilter");

方式三:直接将 Filter 交给 Spring 容器(简单排序)

直接在 Filter 上加 @Component,Spring 自动注册为过滤器。

代码示例

java 复制代码
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;

@Component
public class BeanFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Spring Bean 过滤器执行");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) {}
    @Override
    public void destroy() {}
}

控制顺序

配合 @Order(数值)数值越小越先执行

java 复制代码
@Component
@Order(0)
public class BeanFilter1 implements Filter { ... }

@Component
@Order(1)
public class BeanFilter2 implements Filter { ... }

优缺点

  • ✅ 写法简洁
  • ❌ 部分场景路径配置不如 FilterRegistrationBean 灵活

四、常见实战场景示例(跨域、编码)

统一编码过滤器

java 复制代码
@Component
public class EncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        chain.doFilter(request, response);
    }
}

简单跨域过滤器

java 复制代码
@Component
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setHeader("Access-Control-Allow-Origin", "*");
        resp.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
        resp.setHeader("Access-Control-Max-Age", "3600");
        resp.setHeader("Access-Control-Allow-Headers", "*");
        chain.doFilter(request, response);
    }
}

五、三种方式总结 & 选型建议

  1. 简单单过滤器 :用 @WebFilter + @ServletComponentScan
  2. 多过滤器、需要严格排序/精细路径配置 :优先 FilterRegistrationBean(企业常用)
  3. 快速开发、简单排序@Component + @Order

注意:Filter 无法获取 Spring MVC 的 Controller 方法信息,如需拦截接口、获取注解/方法参数,改用 Interceptor 拦截器

相关推荐
她的男孩40 分钟前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
爱读源码的大都督1 小时前
Claude Code源码分析(三):为什么系统提示词中需要有tools呢?
前端·人工智能·后端
爱勇宝1 小时前
Claude Code 被曝暗藏“隐形检测”代码:封代理不是最可怕的,可怕的是你根本不知道它在干什么
前端·后端·程序员
ITOM运维行者1 小时前
从零搭建企业级服务器监控体系:踩坑实录与架构设计
前端·后端
用户4099322502121 小时前
Vue状态管理入门第四章:组合式store和SSR风险
前端·vue.js·后端
用户34232323763171 小时前
SPI 通信与高速外设驱动详解
后端
魏祖潇2 小时前
SDD 完整指南——Spec 端打底、Story 端交付、留白区
人工智能·后端
feelmylife592 小时前
消息队列可靠投递与幂等消费 -- 从"消息丢了"到"消息别重复"的完整工程实践
后端
雪隐2 小时前
个人电脑玩AI-10让5060 Ti给你打工——部署 Odysseus:终于有个能打的"AI管家"了
人工智能·后端
荣码2 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python