欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 在spring boot工程中使用Filter时,@WebFilter 注解不生效的问题分析和解决方案

在spring boot工程中使用Filter时,@WebFilter 注解不生效的问题分析和解决方案

2024/11/30 12:53:57 来源:https://blog.csdn.net/weixin_71894495/article/details/143805008  浏览:    关键词:在spring boot工程中使用Filter时,@WebFilter 注解不生效的问题分析和解决方案

1. 问题描述

        首先编写一个Filter类并通过@Component放入spring容器中,通过实现jakarta.servlet中提供的Filter接口完成过滤器的创建,代码如下。

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void destroy() {Filter.super.destroy();}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("filter 前置.....");filterChain.doFilter(servletRequest, servletResponse);System.out.println("filter 后置.....");}
}

为了将过滤器配置到目标路径下,通常有两种方法:

        使用servlet提供的@WebFilter注解完成过滤路径的配置。

@Component
@WebFilter(urlPatterns = "/api/*",filterName = "myFilterName") 
public class MyFilter implements Filter {代码同上,省略
}

        使用spring boot推荐的配置类FilterRegistrationBean完成过滤路径的配置。

笔者在使用@WebFilter注解进行过滤路径配置时发现,所有路径下的请求都被过滤了,不受@WebFilter注解中的参数控制,而使用spring推荐的配置类方法则不会出现这个问题。

2. 问题分析

@WebFilter、@WebServlet 和 @WebListener 等与Filter相关的注解均是在Servlet 容器中,spring容器中并没有这些注解,所以即使在Filter类中加上@WebFilter注解并配置好路径参数,spring工程中也读不到这个配置,spring会使用spring配置类的配置,如果spring配置类中没有对Filter进行配置,就会使用默认配置,即针对所以路径进行过滤,所以才会出现以上现象,使用@WebFilter配置类过滤路径,但Filter还是会对所有路径进行过滤。

3. 解决方案

        3.1 spring配置类

        最简单的解决方案就是不使用@WebFilter注解对过滤路径进行配置,而是使用spring推荐的配置类的方式进行配置。

@Configuration  // 专门对 springMVC 底层做一些配置
public class MySpringMVCConfig implements WebMvcConfigurer{@Autowiredprivate MyFilter myFilter;@Beanpublic FilterRegistrationBean getFilter1Registration() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(this.myFilter);//设置过滤器名称和路径,在过滤器类写了的话,这里不用重复写filterRegistrationBean.setName("filter");filterRegistrationBean.addUrlPatterns("/api/*");//设置过滤器执行顺序,数字越小,越早进行过滤,也可设置为负数filterRegistrationBean.setOrder(1);return filterRegistrationBean;}}

3.2 @WebFilter注解      

如果非要使用@WebFilter注解的话:

第一步:需要把@WebFilter添加到容器中,因为spring容器中并没有@WebFilter的注解,这个注解在servlet容器中,故需要在启动类中添加@ServletComponentScan 注解启用 Servlet 容器扫描 @WebFilter@WebServlet@WebListener 注解,将这些组件注册到 Servlet 容器中。

@SpringBootApplication
@ServletComponentScan
public class SpringmvcRestfulCrudApplication {public static void main(String[] args) {SpringApplication.run(SpringmvcRestfulCrudApplication.class, args);}
}

增加此注解后,@WebFilter就成功进入到Serlet容器中,并生效了,能够根据读取@WebFilter中的配置对配置内的路径进行过滤。但如果访问的是@WebFilter配置内的路径,程序会对此路径进行两次过滤,如果访问的路径不在@WebFilter配置内,则依然会被过滤一次。

    这是因为在Filter类中添加了@Component注解,如果同时使用@Component和@ServletComponentScan这两个注解,Filter 类既会被 Spring 容器实例化,也会被 Servlet 容器实例化,导致被实例化两次。spring容器中实例化的Filter依然使用配置类的FilterRegistrationBean配置,如果没有则使用默认配置进行所有路径过滤。

        所以就会出现在启动类增加@ServletComponentScan注解后,如果路径在@WebFilter配置内的访问会被过滤两次,一次是servlet容器实例化的Filter过滤的,另一次是spring容器实例化的Filter过滤。如果路径不在@WebFilter配置内依然会被过滤一次,这一次是spring容器中的Filter使用了默认配置进行的全路径过滤。

第二步:为了使用@WebFilter进行配置,不受spring容器实例化的Filter干扰,即将Filter类中的@Component注解删掉,Filter类不受spring容器控制,也不会进行实例化,这样就不会有两个实例化的Filter进行相互干扰了。

//@Component 不放到spring容器中管理
@WebFilter(urlPatterns = "/api/*",filterName = "myFilterName") 
public class MyFilter implements Filter {代码同上,省略
}

4 总结

        综上所述,如果在spring boot工程中使用过滤器Filter,推荐在配置类中使用FilterRegistrationBean进行过滤路径配置,并在Filter类中添加@Component将Filter类加载到spring容器中。

        如果要使用@WebFilter进行过滤路径的配置,则需要在启动类中添加@ServletComponentScan注解启用Servlet容器扫描@WebFilter注解,并删除Filter类中的@Component注解,防止spring实例化的Filter与Servlet容器实例化的Filter冲突。

今后读者在使用过程中只要意识到自己过滤器Filter是由spring实例化的还是servlet实例化的,两个实例化的Filter所使用的配置方式不一样,要使用对应的配置方式。万万不可同时使用@Component注解和@ServletComponetScan注解。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com