[后端开发] 过滤器相关注解

发布于:2024-04-19 ⋅ 阅读:(40) ⋅ 点赞:(0)

一、背景

使用Springboot框架开发后端,在鉴权的时候使用到了过滤器。但是在测试的过程发现,跨域的过滤器在过滤链中出现了两次,导致前端访问后端接口时报错:The 'Access-Control-Allow-Origin' headers contains multiple values,but only one allowed.错误

在浏览器端比较正常访问接口和报错接口的headers,发现报错接口出现了两次headers,然后开始了debug之路,发现:异常接口跨域过滤器进行了重复注册,最终定位到了是注解的问题。

二、不同注解的作用

1、@Component注解

在Filter类使用了@Component注解,在不指定bean名字的前提下,会默认生成一个类名首字母小写的bean name

当在CorsFilter类上面使用@Component注解,默认生成bean name是corsFilter,访问接口的时候会按照过滤器链按顺序进行过滤;

2、@WebFilter + @ServletComponentScan注解

在Filter类上线使用了@WebFilter注解,在不指定名字的情况下,默认的名字是类的完全限定名,也就是包名+类名,比如:com.example.filters.ExampleFilter。

@ServletComponentScan注解作用:@ServletComponentScan 注解告诉 Spring Boot 在启动时扫描特定的包,以查找使用 @WebFilter@WebServlet@WebListener 注解的类,并将它们注册为相应的 Servlet API 组件。

3、注册过滤器的两种方法

@Component注解

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

@Component
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<ExampleFilter> exampleFilterRegistration() {
        FilterRegistrationBean<ExampleFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new ExampleFilter());
        registration.addUrlPatterns("/example/*");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE); // 设置过滤器的顺序
        return registration;
    }
}

OR

@WebFilter + @ServletComponentScan两个注解必须同时使用

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan("com.example.filters") // 指定过滤器所在的包
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@WebFilter(filterName = "exampleFilter", urlPatterns = "/example/*")
public class ExampleFilter implements Filter {
    // 实现过滤器的逻辑
}

三、其他

定位方法:查看过滤链

虽然有两个过滤器都同时使用了@WebFilter注解和@Component注解,但由于其中一个过滤器在使用@WebFilter注解的时候指定了名字,和@Component默认生成的名字一致,所以在过滤器链中只有一个;

但另一个在使用@WebFilter注解时没有指定名字,所以两个注解分别注册了两个不同名字的bean,导致在调用对应接口时出错。