Spring Boot中过滤器注册@Component与@WebFilter的使用疑惑
嗨,我来帮你理清这个过滤器注册的困惑!其实这个问题的核心在于Spring Boot对Servlet组件(过滤器、Servlet、Listener)的扫描机制,我给你拆解一下:
为什么有些博客只用@WebFilter就能生效?
你看到的那些只用@WebFilter就成功注册过滤器的案例,一定是在Spring Boot的启动类上加了@ServletComponentScan注解!这个注解的作用就是让Spring Boot扫描指定包下带有@WebFilter、@WebServlet、@WebListener的类,并把它们注册到Servlet容器中。很多博客可能默认你知道这个前置条件,所以没特意写出来,才导致你疑惑。
如果你的启动类没加@ServletComponentScan,那单独加@WebFilter的过滤器类根本不会被Spring Boot识别,自然不会生效。
为什么你需要同时用@Component和@WebFilter?
你当前的情况应该是启动类没有加@ServletComponentScan,这时候@Component的作用是把你的XssFilter纳入Spring的Bean管理容器,而@WebFilter里的urlPatterns、filterName这些配置会被Spring读取并应用到这个Bean上,最终实现过滤器的注册和拦截。
不过这里要注意:这种方式其实是Spring的“兼容处理”,本质上是把过滤器作为Spring Bean注册,同时复用了@WebFilter的配置信息,但并不是标准的Servlet组件注册方式。
两种推荐的正确注册方式
给你推荐两种更清晰、不会踩坑的过滤器注册方式:
方式一:@WebFilter + @ServletComponentScan
- 过滤器类只保留
@WebFilter注解:
@WebFilter(urlPatterns = "/*", filterName = "xssFilter") public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { Filter.super.destroy(); } }
- 在Spring Boot启动类上添加
@ServletComponentScan,指定过滤器所在的包(不指定的话默认扫描启动类所在包及其子包):
@SpringBootApplication @ServletComponentScan(basePackages = "com.yourpackage.filter") public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
方式二:@Component + FilterRegistrationBean(更灵活)
这种方式完全不用@WebFilter,通过Spring的配置类手动注册过滤器,能更精细地控制过滤器的顺序、拦截规则等:
- 过滤器类只加
@Component:
@Component public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { Filter.super.destroy(); } }
- 创建一个配置类,用
FilterRegistrationBean来注册:
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean<XssFilter> xssFilterRegistration(XssFilter xssFilter) { FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(xssFilter); registration.addUrlPatterns("/*"); // 设置拦截路径 registration.setName("xssFilter"); // 设置过滤器名称 registration.setOrder(1); // 设置执行顺序,值越小越先执行 return registration; } }
关于SSM项目的补充(你提到没写完的部分)
在传统SSM项目中,没有Spring Boot的自动配置机制,@WebFilter的生效依赖Servlet容器的扫描(比如Tomcat的自动扫描),但通常我们更习惯在web.xml里通过<filter>和<filter-mapping>标签配置过滤器,或者用Spring的@Bean来注册FilterRegistrationBean,和Spring Boot的自动扫描逻辑差异很大,所以不能直接套用Spring Boot的经验。
避坑提醒
别同时用@Component + @WebFilter + @ServletComponentScan!这会导致你的过滤器被注册两次——一次是Spring通过@Component注册,另一次是@ServletComponentScan扫描@WebFilter注册,最终过滤器的doFilter方法会被执行两次,引发不必要的问题。
备注:内容来源于stack exchange,提问作者Blaze

