过滤器的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;
    }
}
相关推荐
EatFan3 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
Maiko Star4 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
现任明教教主~6 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
一条破秋裤7 小时前
Linux 线程创建:pthread_create 与基本回收
java·linux·运维
布吉岛的石头7 小时前
Java 程序员第 49 阶段5:BERT 预训练目标 MLM+NSP 的工程含义
java·人工智能·深度学习·bert·transformer
摇滚侠8 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python
二十雨辰8 小时前
[学成在线]-01项目背景
java
弈栈录9 小时前
Java AI 应用的异步化与高并发设计
java·后端·架构
落魄实习生9 小时前
Agent Scope Java 2.x 系列【2】 ReActAgent
java·开发语言
艸肅9 小时前
Ubuntu 安装 JDK (含手动安装)
java·ubuntu·jdk