过滤器的4种创建方式

1.实现Filter接口,添加@Component成为bean

java 复制代码
@Component
public class MyFilter implements Filter {
    private static final Logger log = LoggerFactory.getLogger(MyFilter.class);

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("1.实现Filter接口,添加@Component成为bean");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String uri = request.getRequestURI();
        if (uri.startsWith("/user/")) {
            log.info("execute plan A");
        } else if (uri.startsWith("/goods/")) {
            log.info("execute plan B");
        } else {
            log.info("execute plan C");
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

这里的 Filter 的全路径是:jakarta.servlet.Filter。

这种创建过滤器的方式默认会拦截所有接口,需要在 doFilter 方法中手动添加处理逻辑。

因为这里的过滤器是一个 bean,可以用 @Order 注解或者实现 Ordered 接口设置优先级。

Ordered 接口 > @Order 注解。

java 复制代码
public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    }
}

Filter 里面有三个方法,init 和 destroy 是默认方法,可以不重写。

如果需要在这个过滤器的生命周期做事情的话再重写。

2.实现Filter接口,通过FilterRegistrationBean注册成为bean

依旧让一个类实现 Filter 接口,但是不需要添加 @Component 注解。

java 复制代码
public class MyFilter implements Filter {
    private static final Logger log = LoggerFactory.getLogger(MyFilter.class);

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("2.实现Filter接口,通过FilterRegistrationBean注册成为bean");
        log.info("do something");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
java 复制代码
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
        FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new MyFilter());
        bean.setOrder(1);
        bean.addUrlPatterns("/*");
        return bean;
    }
}

在配置类中返回 FilterRegistrationBean 对象作为 bean。

在配置类中可以设置拦截规则、优先级。

但是有个问题,这里的 MyFilter 是我们自己手动创建的,new MyFilter() 嘛,所以这个对象不会被 Spring 管理,在 MyFilter 中无法自动注入其他 bean,会抛 NullPointerException。

如果需要在 MyFilter 中注入 bean,就要让 MyFilter 被 Spring 管理,也就是给 MyFilter 添加 @Component 注解。

java 复制代码
@Configuration
public class FilterConfig {
    @Autowired
    private MyFilter myFilter;

    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
        FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(myFilter);
        bean.setOrder(1);
        bean.addUrlPatterns("/*");
        return bean;
    }
}

3.实现Filter接口,添加@WebFilter,启动类添加@ServletComponentScan

java 复制代码
@WebFilter(urlPatterns = "/*", filterName = "myFilter")
public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("3.实现Filter接口,添加@WebFilter,启动类添加@ServletComponentScan");
        log.info("do something");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

MyFilter 要实现 Filter 接口,然后添加 @WebFilter 注解。

java 复制代码
@SpringBootApplication
@ServletComponentScan
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

启动类要添加 @ServletComponentScan 注解,否则 MyFilter 不会生效。

第三种方式比较特殊:

  • MyFilter 中可以注入 bean。
  • 但是无法通过 @Order 注解和 Ordered 接口指定优先级,而是按照类名排序,类名就是字符串嘛,所以是根据字符串排序。(不是 filterName,是类名)

4.继承OncePerRequestFilter,添加@Component成为bean

java 复制代码
@Component
public class MyFilter extends OncePerRequestFilter {
    private static final Logger log = LoggerFactory.getLogger(MyFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("4.继承OncePerRequestFilter,添加@Component成为bean");
        filterChain.doFilter(request, response);
    }
}

OncePerRequestFilter 是 Spring 提供的过滤器,保证一次请求只执行一次。

跟第一种方式一样,可以注入 bean,可以设置优先级。

也可以像第二种方式一样,在配置类中注册到 FilterRegistrationBean 中。

java 复制代码
@Configuration
public class FilterConfig {
    @Autowired
    private MyFilter myFilter;

    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
        FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(myFilter);
        bean.setOrder(1);
        bean.addUrlPatterns("/api/*");
        return bean;
    }
}
相关推荐
SL_staff3 小时前
周报越厚问题越拖?用结构化执行机制让周报回归决策价值
java·spring cloud·开源
梅梅绵绵冰3 小时前
JVM虚拟机
java·开发语言·jvm
golang学习记3 小时前
Python vs Go:2026年到底该怎么选
java·vscode·python·golang·pycharm·goland
Shaoshing3 小时前
消息顺序
java·开发语言
我命由我123454 小时前
SQL 检测脚本
java·数据库·sql·功能测试·单元测试·压力测试·可用性测试
Hpc_Fun4 小时前
GPU 工作站品牌怎么比?五把可核验尺子、加权评分脚本与场景重排
java·信创·gpu工作站·品牌对比·加权评分
const_qiu4 小时前
第四章 03:4.3 Tools —— 让 Agent 会用工具
java·人工智能
Rain的Java大神之路4 小时前
百万并发直播弹幕系统设计全解:看懂了扇出,你就看懂了高并发的八成
java·后端·面试
\光辉岁月/4 小时前
2.异常类
java·开发语言·异常类
十年Java程序媛4 小时前
JVM 基础与 GC 垃圾回收详解|可达性分析、分代模型、垃圾收集器、STW
java·开发语言·jvm·spring boot·后端·面试