Java / Spring MVC:为子线程提供请求上下文

我有问题,我想将我的Spring WebMVC应用程序的一些进程外包到单独的Threads中.这很容易并且有效,直到我想使用一个使用全局请求的类userRightService.这在线程中不可用,我们遇到了一个问题,这几乎是可以理解的.

这是我的错误:

java.lang.RuntimeException:
org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'scopedTarget.userRightsService': 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: Cannot ask for request attribute - 
request is not active anymore!

好的,够清楚了.我试图通过实现此解决方案来保持请求上下文:

How to enable request scope in async task executor

这是我的runnable类:

@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class myThread implements Runnable {

  private RequestAttributes context;

  public DataExportThread(RequestAttributes context) {
    this.context = context;
  }

  public void run() {
    RequestContextHolder.setRequestAttributes(context);

这就产生了它:

final DataExportThread dataExportThread = 
   new myThread(RequestContextHolder.currentRequestAttributes());

final Thread thread = new Thread(myThread);
thread.setUncaughtExceptionHandler((t, e) -> {...});
thread.start();

据我所知,我们将currentRequestAttributes存储在线程中,然后在运行时,我们将它们恢复为currentRequestAttributes …对我来说听起来很稳固,但错误仍然存​​在.我认为我在为我的案例调整解决方案时犯了一些错误.也许有人可以帮我找到错误.

在我使用不同的解决方案(见下文)之前经历了很多stackoverflow-threads之前,我接下来可以尝试其他的东西,但这个对我来说似乎是最清晰和最简单的,所以我希望有人可以帮我找到实现中的错误或解释为什么这是错误的方法.

> Scope ‘session’ is not active for the current thread; IllegalStateException: No thread-bound request found
> Accessing request scoped beans in a multi-threaded web application
> Using a request scoped bean outside of an actual web request
> InheritableThreadLocal value not inherited by ExecutorService threads
> How to enable request scope in async task executor
> Setting ThreadContext for all threads in application
> Spring mvc request scope context across threads

我已经尝试过这个没有成功:

> How to enable request scope in async task executor

如果这很重要:

<org.springframework-version>4.3.4.RELEASE</org.springframework-version>

顺便说一句:我知道以某种方式重构应用程序会更好,因为线程中不需要请求但在这种情况下这非常复杂,我真的希望我能避免这种情况.

EDIT1:

无法在线程中创建的Bean如下所示:

@Service("userRightsService")
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserRightsService {

EDIT2:

我也试过这个:

> Setting ThreadContext for all threads in application

但背景总是空的……

我无法重现这个问题,因为我不确定你是如何创建/注入UserRightsService的,但我有一些建议你可以试试.

我想问题是RequestAttributes在请求结束时失效(这就是为什么异常说不能请求请求属性 –
请求不再处于活动状态),这在您的任务正在运行时发生.

相反,您可以尝试注入生成线程的UserRightsService,并将此实例作为参数传递给线程.这样就可以毫无问题地创建UserRightsService,因为请求仍然可用.

即便如此,在请求结束后尝试访问RequestAttributes可能会失败.在这种情况下,我建议在请求结束之前,即在运行线程之前复制所需的所有值.

如果这对您不起作用,请提供有关如何在任务内初始化UserRightsService的更多信息.

祝好运!

P.S.:我认为线程类中的范围注释是无用的,因为任务对象是手动创建的,而不是由spring管理的.

翻译自:https://stackoverflow.com/questions/52502666/java-spring-mvc-provide-request-context-to-child-threads

转载注明原文:Java / Spring MVC:为子线程提供请求上下文