在 Spring Boot 中配置 RequestContextListener

Configuring RequestContextListener in SpringBoot

我有一个 Spring-Boot 应用程序,它使用 Spring-Security。我有一个请求范围的 bean,我想将其自动装配到安全过滤器链中的自定义过滤器之一,但目前它不工作。

我知道需要一些配置才能在 DispatcherServlet 之外使用请求范围的 beans,并且已经阅读了这篇文章http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-other但是还没有取得任何成功:

For Servlet 3.0+, this can done programmatically via the WebApplicationInitializer interface.

(我使用的是最新的 Tomcat servlet 3+ 也是如此)

我已经尝试同时使用 RequestContextListener 和 RequestContextFilter(文档说它们和 DispatcherServlet 做完全相同的事情),但是在这两种情况下我仍然会出错,因为我的自动装配对象为空:

我尝试注册过滤器

@Configuration
@ComponentScan
@EnableAutoConfiguration
class Application extends SpringBootServletInitializer  {

    @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) {
        application.sources( Application )
    }

    @Override public void onStartup( ServletContext servletContext ) throws ServletException {
        super.onStartup( servletContext )
        servletContext.addFilter("requestContextFilter", new RequestContextFilter() ).addMappingForUrlPatterns(null, false, "/*")
    }

我尝试注册监听器

@Configuration
@ComponentScan
@EnableAutoConfiguration
class Application extends SpringBootServletInitializer  {

    @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) {
        application.sources( Application )
    }

    @Override public void onStartup( ServletContext servletContext ) throws ServletException {
        super.onStartup( servletContext )
        servletContext.addListener( new RequestContextListener() ) 
    }

我是不是遗漏了什么明显的东西?我查看了 Spring Boot 的自动配置源代码,但还没有遇到任何问题。


更新

我是个白痴,我在 Spring 安全配置中添加了过滤器,在 configure() 方法中:

http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )

但尚未将新过滤器注册为 Bean。根据下面 M. Denium 的评论,我不需要所有额外的配置显式添加 listener/filter,只需注册 bean 就足够了。

详见update/comments,这是我自己的愚蠢造成的。

Spring-Boot 能够将 Request/Session 范围内的 bean 自动装配到 DispatcherServlet 之外的过滤器中 根据 Spring 的文档,我们需要添加RequestContextListenerRequestContextFilter 以启用此功能:

To support the scoping of beans at the request, session, and global session levels (web-scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes, singleton and prototype.) ...

If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, or DispatcherPortlet, then no special setup is necessary: DispatcherServlet and DispatcherPortlet already expose all relevant state.

为了处理这个问题,我需要注册一个 RequestContextListener bean:

@Bean public RequestContextListener requestContextListener(){
    return new RequestContextListener();
} 

如果您不注册该 bean,您将收到一条错误消息,指出您正在尝试访问 DispatcherServlet 之外的 Request 范围。

我遇到的问题(自动装配对象未被注入)是由于我只是将我的自定义过滤器注册为标准 class 实例,而不是 Spring 托管 bean:

http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )

为了解决这个问题,我只是将 PreAuthFilter 的创建移动到单独的 @Bean 方法中,然后 @Autowired 功能就可以正常工作了。