我正在做一个Spring Boot项目,运行正常。
我想注册一个过滤器,但是我发现过滤器需要同时使用@Component和@WebFilter来拦截请求。
但是,我注意到一些关于Spring Boot的博客只使用了@WebFilter,并且过滤器仍然被注册,这让我很困惑。
@Component
@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的常规SSM项目,发现无论我是否包含@Component,使用@WebFilter注册的过滤器仍然以相同的方式工作。
我也尝试过重写一个Spring Boot项目,但没有使用嵌入式Tomcat;相反,我使用了外部 Tomcat 服务器。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
此时,当我同时包含@Component和@WebFilter时,出现错误:
“无法在 servlet 上下文中注册‘filter xssFilter’。可能已经注册了?”
当我去掉@Component,只使用@WebFilter时,程序运行正常,请求被过滤器拦截。
我在网上看了很多帖子,但仍然无法理解这个问题。
使用
@Component
+ @WebFilter
时,您实际上是在嵌入式 Tomcat 中注册了两次过滤器:
@Component
通过Spring的组件扫描来注册@WebFilter
通过Servlet容器的扫描来注册这就是使用这两种注释都有效的原因,但这不是推荐的方法
但是在传统 Spring MVC(外部 Tomcat)中:
@WebFilter
是一个标准的 Jakarta EE 注释,由 servlet 容器 (Tomcat) 处理@Component
是Spring框架注解使用外部Tomcat时,servlet容器直接处理@WebFilter注册 这就是为什么在使用这两个注释时会收到“已注册”错误的原因
=> 使用 Just
@WebFilter
需要在 Spring Boot 应用程序中使用 @ServletComponentScan
,此注释可以扫描 servlet 组件,包括 @WebFilter