在 Spring Boot 中配置 RequestContextListener
Posted
技术标签:
【中文标题】在 Spring Boot 中配置 RequestContextListener【英文标题】:Configuring RequestContextListener in SpringBoot 【发布时间】:2015-07-27 01:23:31 【问题描述】:我有一个使用 Spring-Security 的 Spring-Boot 应用程序。我有一个请求范围的 bean,我想将它自动装配到安全过滤器链中的一个自定义过滤器中,但目前它不起作用。
我了解在 DispatcherServlet 之外使用请求范围的 bean 需要进行一些配置,并且已阅读此 http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-other 但尚未取得任何成功:
对于 Servlet 3.0+,这可以通过 WebApplicationInitializer 接口。
(我使用的是最新的 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 的自动配置源代码,但还没有遇到任何东西。
更新
我是个白痴,我在我的 SpringSecurity 配置中添加了我的过滤器,在 configure()
方法中:
http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )
但尚未将新过滤器注册为 Bean。根据下面 M. Denium 的评论,我不需要所有额外的配置显式添加侦听器/过滤器,只需注册 bean 就足够了。
【问题讨论】:
你让它变得复杂。只需添加一个构造RequestContextListener
的@Bean
方法。 Spring Boot 将完成剩下的工作。但是,由于 Spring 安全过滤器链受 Spring 控制,因此不需要这样做,因此除非您在实际过滤器链之外执行操作,否则您需要注册它,否则它应该可以工作。
谢谢@M.Deinum - 原来我是个白痴 - 我已经用细节更新了问题,但基本上没有正确注册过滤器。
@M.Deinum: 自定义AuthenticationProvider
是否被视为“在实际过滤器链之外”?如果没有,那么这样的提供者是否可以访问已初始化的 RequestContextHolder
而无需显式配置 RequestContextListener
?
【参考方案1】:
正如更新/cmets 中所详述的,这是我自己的愚蠢造成的。
Spring-Boot 能够将请求/会话范围的 bean 自动装配到 DispatcherServlet
之外的过滤器中。根据 Spring 的文档,我们需要添加 RequestContextListener
或 RequestContextFilter
以启用此功能:
在请求、会话和全局中支持 bean 的作用域 会话级别(网络范围的 bean),一些小的初始配置是 在定义 bean 之前需要。 (此初始设置不是 标准范围、单例和原型所需的。) ...
如果你在 Spring Web MVC 中访问作用域 bean,实际上是在一个 由 Spring DispatcherServlet 处理的请求,或 DispatcherPortlet,则无需特殊设置: DispatcherServlet 和 DispatcherPortlet 已经公开了所有相关的 状态。
为了处理这个问题,我需要注册一个 RequestContextListener bean:
@Bean public RequestContextListener requestContextListener()
return new RequestContextListener();
如果您不注册该 bean,您将收到一条错误消息,指出您正在尝试访问 DispatcherServlet 之外的 Request 范围。
我遇到的问题(自动装配的对象没有被注入)是因为我只是将我的自定义过滤器注册为标准类实例,而不是 Spring 托管 bean:
http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )
为了解决这个问题,我只是将 PreAuthFilter
的创建移到了单独的 @Bean
方法中,然后 @Autowired
功能就可以正常工作了。
【讨论】:
谢谢你,不要对自己太苛刻。愚蠢。你的问题和回答真的帮助了我。 谢谢,这对我也有帮助,但我没有注册RequestContextFilter
bean,而是在我的 ResourceServerConfigurerAdaptor
扩展中添加以下行:addFilterAfter(new RequestContextFilter(), CsrfFilter.class)
以上是关于在 Spring Boot 中配置 RequestContextListener的主要内容,如果未能解决你的问题,请参考以下文章
spring boot拦截器中获取request post请求中的参数