spring 在实际 Web 请求之外使用请求范围的 bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17424739/
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 06:03:19  来源:igfitidea点击:

Using a request scoped bean outside of an actual web request

springspring-aopspring-integration

提问by Diego Urenia

I have a web application that has a Spring Integration logic running with it in a separated thread. The problem is that at some point my Spring Integration logic tries to use a request scoped bean and then i get the following errors:

我有一个 Web 应用程序,它在一个单独的线程中运行了一个 Spring Integration 逻辑。问题是,在某些时候,我的 Spring Integration 逻辑尝试使用请求范围的 bean,然后我收到以下错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.tenantContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.


Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

I have the ContextLoaderListener set:

我有 ContextLoaderListener 设置:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

My Scoped Bean is annotated like that(since I heard that proxing my bean would help):

我的 Scoped Bean 是这样注释的(因为我听说代理我的 bean 会有所帮助):

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)  
public class TenantContext  implements Serializable {

Is what I'm doing possible? If yes, what am I missing here? If no, any other suggestions on how I can achieve that?

我正在做的事情可能吗?如果是,我在这里错过了什么?如果没有,关于我如何实现这一目标的任何其他建议?

采纳答案by Gary Russell

You can only use request (and session) -scoped beans on the web container thread on which the request is running.

您只能在运行请求的 Web 容器线程上使用请求(和会话)范围的 bean。

I presume that thread is waiting for an async reply from your SI flow?

我认为线程正在等待来自您的 SI 流的异步回复?

If so, you can bind the request-scoped bean to the message, perhaps in a header, or somewhere in the payload.

如果是这样,您可以将请求范围的 bean 绑定到消息,可能在标题中,或者在有效负载中的某个位置。

回答by Deepak

For Spring 4 Frameworks add servletContext.addListener(new RequestContextListener());

对于 Spring 4 框架添加 servletContext.addListener(new RequestContextListener());

public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { RootConfiguration.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebMvcConfiguration.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] { new HiddenHttpMethodFilter() };
    }

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

回答by Thilak

Use RequestContextFilter with the property threadContextInheritable set to true. This makes the child thread to inherit the parent's context, which contains the request object itself. Also make sure that the executor doesn't reuse the threads in the pool, because the request object is very specific to that request and cannot be shared across various requests. One such executor is SimpleAsyncTaskExecutor.

使用 RequestContextFilter 并将属性 threadContextInheritable 设置为 true。这使得子线程继承父的上下文,其中包含请求对象本身。还要确保执行程序不会重用池中的线程,因为请求对象非常特定于该请求,并且不能在各种请求之间共享。SimpleAsyncTaskExecutor 就是一个这样的执行器。

For more info refer Scope 'session' is not active for the current thread; IllegalStateException: No thread-bound request found.

有关更多信息,请参阅当前线程的范围“会话”未激活;IllegalStateException: No thread-bound request found