Java/Spring MVC:向子线程提供请求上下文 [英] Java/Spring MVC: provide request context to child threads

查看:500
本文介绍了Java/Spring MVC:向子线程提供请求上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have the Problem, that I want to outsource some processes of my Spring WebMVC application into separate Threads. That was easy enough and works, until I want to use a class, userRightService, which uses the global request. That's not available in the threads, and we get a problem, that's pretty much understandable.

这是我的错误:

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!

好的,足够清楚.我正在尝试通过实施以下解决方案来保留请求上下文:

Okay, clear enough. I am trying to keep the request context by implementing this solution:

如何在异步中启用请求范围任务执行者

这是我的可运行类:

@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 ...对我来说听起来很可靠,但错误仍然存​​在.我认为在为我的案例调整解决方案时犯了一些错误.也许有人可以帮助我找到错误.

As far as I understood, we store the currentRequestAttributes in the thread and then, when running, we restore them currentRequestAttributes... sounded solid to me, but the error is still there. I think I made some mistake adapting the solution for my case. maybe someone can help me finding the error.

在我尝试使用不同解决方案的大量stackoverflow线程之前(请参见下文),因此我可以尝试其他方法,但是对于我来说,这似乎是最清晰,最简单的方法,所以我希望有人可以帮助我发现错误在实施中进行解释,或者解释为什么这是错误的方法.

Before I went through a lot of stackoverflow-threads with different solutions (see below), so I could try something else next, but this one seemed the clearest and simplest to me, so I hope someone could help me finding the mistake in the implementation or explain why it's the wrong approach.

  • 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

我已经尝试过此方法,但没有成功:

I already tried this one without success:

这很重要:

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

BTW:我知道以某种方式重组应用程序会更好,线程中不需要该请求,但是在这种情况下这很复杂,我真的希望我能避免这种情况.

BTW: I know that it would be better to restructure the application in a way, that the request is not needed in the thread but that's very complicated in that case and I really hope I could avoid this.

-

Edit1:

无法在线程中创建的Bean是这样启动的:

The Bean which can not be created in the thread starts like this:

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

-

Edit2:

我也尝试过这个:

但是上下文始终是空的...

But context is always empty...

推荐答案

对于正在搜索的用户.借助Master_Ex的提示,我找到了解决方案:

For those, who are searching. With the help of Master_Ex's hints I found a solution:

在可运行环境中:

private HttpServletRequest request;

public void run() {

    final RequestContextListener rcl = new RequestContextListener();
    final ServletContext sc = request.getServletContext();
    rcl.requestInitialized(new ServletRequestEvent(sc, request));

然后在UserRightService中,我调用一个执行以下操作的函数:

And in the UserRightService I make a call to a function which does the following:

    SecurityContext context = SecurityContextHolder.getContext();
    Authentication auth = context.getAuthentication();

    context.setAuthentication(getDataExportAuthentication(exportingUser));

@Master_Ex的谢谢,您的帖子非常有帮助.很抱歉,我来不及给您赏金,否则我会把它标记为正确的赏金.

@Master_Ex's Thank You, your post was very helpful. So sorry that I am too late to give you the bounty, otherwise I would have marked it as the correct one.

这篇关于Java/Spring MVC:向子线程提供请求上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆