当前位置: 首页 > 知识库问答 >
问题:

无法覆盖或禁用spring boot实例化过滤器,导致过滤器链中出现重复条目

仰成天
2023-03-14

我有一个组件类:

public class FooFilter implements Filter {
    private FooService fooService; //spring-injected dependency
    @Override public void init(FilterConfig filterConfig) {}
    @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){}
    @Override public void destroy() {}
}

在springConfigured.xml中定义:

<context:spring-configured />
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <bean class="com.foo.filter.FooFilter" scope="prototype" autowire="byType"/>

</beans>

过滤器是使用FilterRegistrationBean在我们的过滤器链中配置的:

@Configuration
public class FooFilterRegistrationConfig {
    private List<String> URL_PATTERNS = Arrays.asList("foo", "bar");
    @Bean
    public FilterRegistrationBean fooFilter(FooFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(filter);
        registration.setName("FooFilter");
        registration.setUrlPatterns(URL_PATTERNS);
        registration.setOrder(4);
        return registration;
    }

    //and some more
}

使用此设置,我们最终在我们的过滤器链中得到两个FooFilter。日志:

//a bunch of filters
2017-10-16 16:34:37,468 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Mapping filter: 'FooFilter' to urls: [*.jsp, *.do, *.faces, *.action, /mvc/*]
//some more filters
2017-10-16 16:34:37,468 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Mapping filter: 'com.foo.web.filter.FooFilter#0' to: [/*]

对于像这样的问题,其他一些答案建议使用RegistrationConfig禁用过滤器。如果我尝试使用注册禁用FilterRegistrationConfig中的过滤器。setEnabled(false),最后我仍然得到了额外的过滤器。

2017-10-16 16:22:46,078 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Filter FooFilter was not registered (disabled)
...
2017-10-16 16:22:46,079 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Mapping filter: 'com.foo.filter.FooFilter#0' to: [/*]

我已经尝试在我们的FilterRegistrationConfig中完全删除对这个过滤器的引用,并直接使用FooFilter类上的Order注释,但因为我们在xml中指定这个bean,而不使用组件扫描,所以我似乎无法获得正确应用Url模式的WebFilter注释。

如果能从我的过滤链中找到任何关于如何摆脱这个Spring启动创建的FooFilter#0的提示,我们将不胜感激!

编辑:

我已经尝试从xml中删除bean定义。现在我无法将其注入FilterRegistrationBean方法,因为这会导致“找不到‘FooFilter’类型的bean”错误。

@Bean
public FilterRegistrationBean fooFilter(FooFilter filter) { //no beans of 'FooFilter' type found
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(filter);
    registration.setName("FooFilter");
    registration.setUrlPatterns(URL_PATTERNS);
    registration.setOrder(4);
    return registration;
}

然而,如果我在这里手动实例化一个FooFilter,我稍后会遇到问题,因为FooFilter包含许多spring管理的依赖项,这些依赖项没有被注入:

@Bean
public FilterRegistrationBean fooFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new FooFilter()); //works fine here, but Spring does not inject dependencies into this object I created, so null pointers later
    registration.setName("FooFilter");
    registration.setUrlPatterns(URL_PATTERNS);
    registration.setOrder(4);
    return registration;
}

共有1个答案

唐煜
2023-03-14

FilterRegistrationBean创建您的FooFilter bean,您不必单独创建它,请删除FooFilter的bean(以下一行)

<bean class="com.foo.filter.FooFilter" scope="prototype" autowire="byType"/>

注意:当Spring容器创建bean FilterynstrationBean时,它也会创建一个bean的FolFilter,就像你提到的那样。
registration.setName("FooFilter"); // FooFilter是bean的名称

 类似资料:
  • 主要内容:FilterChain 接口,Filter 链的拦截过程,Filter 链中 Filter 的执行顺序,示例在 Web 应用中,可以部署多个 Filter,若这些 Filter 都拦截同一目标资源,则它们就组成了一个 Filter 链(也称过滤器链)。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到传递给目标资源。 FilterChain 接口 javax.servlet 包中提供了一个 FilterChain 接口,该接口由容器实现。容器将其实例对象

  • 问题内容: 是否有可能扩展现有的“标准”过滤器(,,等)?在我的情况下,我需要从YYYYMMDDhhmmss格式解析日期,因此我想扩展(或覆盖)过滤器,而不是编写自己的过滤器。 问题答案: 我不确定我是否正确理解了您的问题,但是如果您想扩展现有过滤器的功能,则可以创建一个装饰现有过滤器的新过滤器。例: 然后,在您的模板中: 上面已经说了,如果您只是想根据给定的格式格式化日期,可以使用现有的日期过滤

  • 我已将过滤器配置如下,但在Spring Security Filter链之前不会调用它。我已将顺序设置为零 我使用的是Spring Boot 1.3,它支持在过滤器上设置顺序

  • 问题内容: 我的应用程序中有2个过滤器。根据某些条件,我想选择是否执行第二个过滤器。有没有办法做到这一点? 我做了一些谷歌搜索,但没有成功。我希望请求继续执行而不执行第二个过滤器。那可能吗? 任何帮助将不胜感激。 问题答案: 您可以在请求中设置一个属性,然后在第二个过滤器中对其进行检查。 您可以像这样简化上面的代码: 这样,您只需检查属性“ executeSecondFilter”的存在

  • 我所拥有的 预期产出 实际产量 这只是一个例子。在我的真实代码中,我正在对我的全局状态(useContext, useReduer)执行删除操作。 是一个ID数组。

  • 当我调用我的服务时,我的这个URL: 我有这个堆栈跟踪: 什么是平均健康有一个空的筛选器列表?