【问题标题】:Cannot override or disable spring boot-instantiated Filter, resulting in duplicate entries in filter chain无法覆盖或禁用 spring boot-instantiated 过滤器,导致过滤器链中的条目重复
【发布时间】:2018-03-28 12:30:25
【问题描述】:

我有一个组件类:

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 禁用过滤器。如果我尝试使用 registration.setEnabled(false) 禁用 FilterRegistrationConfig 中的过滤器,最后我仍然会得到额外的过滤器。

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 类上使用@Orderannotation,但是因为我们在我们的xml 中指定了这个bean,而不是使用组件扫描,我似乎无法让 @WebFilterannotation 正确应用 URL 模式。

任何关于如何从我的过滤器链中摆脱这个 spring boot-created 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 包含许多未注入的弹簧管理依赖项:

@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;
}

【问题讨论】:

  • 只需删除该 xml 中的 FooFilter bean,它已经由 FilterRegistrationBean 创建
  • 您的过滤器是原型范围的,所以是的,您最终会得到 2 个实例,只需将其设为单例范围。

标签: java spring spring-boot filter servlet-filters


【解决方案1】:

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

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

注意: 当 spring 容器创建 bean FilterRegistrationBean 时,它还创建了一个 FooFilter,正如您所提到的。
registration.setName("FooFilter"); // FooFilter 是 bean 的名称

【讨论】:

  • 感谢您的回复!我试过删除这个 bean 声明,但是如果我手动创建 FooFilter,FooFilter 引用了一些其他的 spring-managed 依赖项,这些依赖项不会被注入。更新了最初的问题,提供了更多细节。
  • 那些依赖是什么?你不能在创建 foofilter 时设置它们
  • 它们是 spring 注入的其他 bean,我在注册配置或 FooFilter 实例中没有引用它们。当我删除 FooFilter 的 xml 定义时,我似乎能够在 filterConfig 中添加它的唯一方法是使用 new FooFilter() 实例化它,但是 Spring 不会将任何托管依赖项注入该实例。
  • 我的意思是像 New foofilter () 一样创建它。并询问 spring 需要注入 foo 过滤器的那些依赖项是什么,你不能设置它们。也许你可以显示错误堆栈
  • 您正在创建新的 foofilter () 。当然 spring 不会自己设置任何东西。我相信你必须手动设置它们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 2015-05-08
  • 2014-01-06
  • 2010-12-18
  • 2015-05-22
  • 1970-01-01
相关资源
最近更新 更多