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

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

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

一、前置说明

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

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

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

1. 编写自定义过滤器

importjavax.servlet.*;importjavax.servlet.annotation.WebFilter;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;// 拦截所有请求 /*@WebFilter(filterName="MyFilter",urlPatterns="/*")publicclassMyFilterimplementsFilter{// 初始化(容器启动执行一次)@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{System.out.println("过滤器初始化");}// 核心拦截逻辑(每次请求都会执行)@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletRequestreq=(HttpServletRequest)request;HttpServletResponseresp=(HttpServletResponse)response;// 放行前逻辑(前置处理)System.out.println("请求地址:"+req.getRequestURI());// 放行,执行后续过滤器/接口chain.doFilter(request,response);// 放行后逻辑(后置处理,响应返回客户端前)System.out.println("请求结束");}// 销毁(容器关闭执行一次)@Overridepublicvoiddestroy(){System.out.println("过滤器销毁");}}

2. 启动类开启注解支持

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

importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication@ServletComponentScan// 关键注解:扫描 Servlet、Filter、ListenerpublicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}

优缺点

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

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

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

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

importjavax.servlet.*;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;publicclassOrderFilter1implementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{System.out.println("【过滤器1】执行");chain.doFilter(request,response);System.out.println("【过滤器1】结束");}@Overridepublicvoidinit(FilterConfigfilterConfig){}@Overridepublicvoiddestroy(){}}
publicclassOrderFilter2implementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{System.out.println("【过滤器2】执行");chain.doFilter(request,response);System.out.println("【过滤器2】结束");}@Overridepublicvoidinit(FilterConfigfilterConfig){}@Overridepublicvoiddestroy(){}}

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

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

importorg.springframework.boot.web.servlet.FilterRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassFilterConfig{@BeanpublicFilterRegistrationBean<OrderFilter1>filter1(){FilterRegistrationBean<OrderFilter1>bean=newFilterRegistrationBean<>();bean.setFilter(newOrderFilter1());bean.addUrlPatterns("/*");// 拦截路径bean.setOrder(1);// 执行顺序:1 > 2returnbean;}@BeanpublicFilterRegistrationBean<OrderFilter2>filter2(){FilterRegistrationBean<OrderFilter2>bean=newFilterRegistrationBean<>();bean.setFilter(newOrderFilter2());bean.addUrlPatterns("/*");bean.setOrder(2);// 顺序靠后returnbean;}}

执行顺序

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

常用配置扩展

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

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

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

代码示例

importorg.springframework.stereotype.Component;importjavax.servlet.*;importjava.io.IOException;@ComponentpublicclassBeanFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{System.out.println("Spring Bean 过滤器执行");chain.doFilter(request,response);}@Overridepublicvoidinit(FilterConfigfilterConfig){}@Overridepublicvoiddestroy(){}}

控制顺序

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

@Component@Order(0)publicclassBeanFilter1implementsFilter{...}@Component@Order(1)publicclassBeanFilter2implementsFilter{...}

优缺点

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

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

统一编码过滤器

@ComponentpublicclassEncodingFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");chain.doFilter(request,response);}}

简单跨域过滤器

@ComponentpublicclassCorsFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletResponseresp=(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 拦截器