spring 在 SpringBoot 中配置 RequestContextListener

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30254079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:34:21  来源:igfitidea点击:

Configuring RequestContextListener in SpringBoot

springspring-mvcspring-securityspring-boot

提问by rhinds

I have a Spring-Boot application which uses Spring-Security. I have a request scoped bean that I want to autowire into one of my custom Filters in the security filter chain, but at the moment it is not working.

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

I understand that some config is needed to use request scoped beans outside of the DispatcherServlet, and have read this http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-otherBut have not had any success yet:

我知道需要一些配置才能在 DispatcherServlet 之外使用请求范围的 bean,并且已经阅读了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.

对于 Servlet 3.0+,这可以通过 WebApplicationInitializer 接口以编程方式完成。

(I am using latest Tomcat so is servlet 3+)

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

I have tried using both the RequestContextListener and the RequestContextFilter (docs say that they, and the DispatcherServlet, do the exact same thing), but in both cases I still get errors because my autowired object is null:

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

My attempt to register the Filter

我尝试注册过滤器

@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, "/*")
    }

My attempt to register the Listener

我尝试注册监听器

@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() ) 
    }

Am I missing something obvious? I have had a look at the auto config source code for Spring Boot and haven't come across anything yet.

我错过了一些明显的东西吗?我已经查看了 Spring Boot 的自动配置源代码,但还没有遇到任何问题。



UPDATE

更新

I was being an idiot, I had added my Filter in my SpringSecurity configuration, inside the configure()method:

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

http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )

but hadn't registered the new Filter as a Bean. As per M. Denium's comment below, I didn't need all that additional config explicitly adding the listener/filter, just registering the bean was enough.

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

回答by rhinds

As detailed in the update/comments, this was caused by my own stupidity.

正如更新/评论中所详述的,这是由我自己的愚蠢造成的。

Spring-Boot is able to autowire Request/Session scoped beans into filter's that are outside of the DispatcherServletAs per Spring's documentation, we need to add the RequestContextListeneror RequestContextFilterto enable this functionality:

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

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.

为了在请求、会话和全局会话级别(网络范围的 bean)支持 bean 的范围,在定义 bean 之前需要一些小的初始配置。(标准范围、单例和原型不需要此初始设置。)...

如果您在 Spring Web MVC 中访问作用域 bean,实际上是在 Spring DispatcherServlet 或 DispatcherPortlet 处理的请求中,则不需要特殊设置:DispatcherServlet 和 DispatcherPortlet 已经公开了所有相关状态。

To handle this, I needed to register a RequestContextListener bean:

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

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

If you don't register that bean, you will get an error stating that you are trying to access the Request scope outside of DispatcherServlet.

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

The problem I experienced(autowired objects just not being injected) was caused by the fact that I was just registering my custom filter as a standard class instance, not a Spring managed bean:

我遇到的问题(只是没有注入自动装配的对象)是因为我只是将自定义过滤器注册为标准类实例,而不是 Spring 管理的 bean:

http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )

To solve this, I just moved the creation of the PreAuthFilterto a sepearte @Beanmethod, the @Autowiredfunctionality then worked fine.

为了解决这个问题,我只是将 的创建PreAuthFilter移到了 sepearte@Bean方法,@Autowired然后该功能运行良好。