过滤器的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;
    }
}
相关推荐
大圣编蚕1 小时前
Java ByteArrayInputStream 详解:从入门到实战
java·开发语言·算法
程序员阿明1 小时前
idea把插件啥的不默认放在C盘
java·ide·intellij-idea
linweidong2 小时前
中科闻歌Java面试题及参考答案
java·python·大模型·提示词·ai agent·mcp·rag原理
OpenAnolis小助手2 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
ForteScarlet2 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·java·开发语言·开源·kotlin·jetbrains
萧瑟余晖2 小时前
Java深入解析篇六十二之安全机制详解
java·开发语言
小刘在重生~3 小时前
Java 常用类|包装类 装箱拆箱、Integer 缓存面试题
java·python·缓存
Orange_sparkle3 小时前
Pi Agent vs LangGraph:从人机交互、企业 RAG 到持久化工作流的完整选型指南
java·网络·人机交互
Wang's Blog5 小时前
Java框架快速入门: Spring Security+OAuth2之过滤器与过滤器链
java·开发语言·spring