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);
}
}
五、三种方式总结 & 选型建议
- 简单单过滤器 :用
@WebFilter + @ServletComponentScan - 多过滤器、需要严格排序/精细路径配置 :优先
FilterRegistrationBean(企业常用) - 快速开发、简单排序 :
@Component + @Order
注意:Filter 无法获取 Spring MVC 的
Controller 方法信息,如需拦截接口、获取注解/方法参数,改用 Interceptor 拦截器。