首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java/Spring MVC:向子线程提供请求上下文

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

Stack Overflow用户
提问于 2018-09-26 00:20:25
回答 2查看 8.2K关注 0票数 9

我有一个问题,我想把我的Spring应用程序的一些进程外包到单独的WebMVC中。这很简单,而且很有效,直到我想使用一个类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……对我来说听起来很可靠,但错误仍然存在。我想我犯了一些错误,使解决方案适合我的情况。也许有人能帮我找出错误。

在我经历了许多不同解决方案的堆栈溢出线程之前(见下文),所以我可以尝试下一步,但这个对我来说似乎是最清楚和最简单的,所以我希望有人能帮助我找到实现中的错误或解释为什么它是错误的方法。

我已经试过了,但没有成功:

如果这很重要:

<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:

我也试过这个:

但是上下文总是空的..。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-08 15:51:09

对于那些正在搜索的人来说。在Master_Ex的提示下,我找到了一个解决方案:

在runnable:

private HttpServletRequest request;

public void run() {

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

在UserRightService中,我调用了一个函数,该函数执行以下操作:

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

    context.setAuthentication(getDataExportAuthentication(exportingUser));

@Master_Ex的谢谢,你的帖子非常有帮助。非常抱歉,我来得太晚了,不能给你赏金,否则我会把它标记为正确的。

票数 2
EN

Stack Overflow用户

发布于 2018-09-29 05:58:14

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

我猜问题是RequestAttributes在请求结束时失效(这就是异常显示Cannot ask for request attribute - request is not active anymore的原因),这是在任务运行时发生的。

相反,您可以尝试在生成线程的位置注入UserRightsService,并将此实例作为参数传递给线程。这样,创建UserRightsService应该没有问题,因为请求应该仍然可用。

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

如果这对你不起作用,请提供一些关于如何在任务中初始化UserRightsService的更多信息。

祝好运!

附言:我认为你的线程类中的作用域注解是无用的,因为任务对象是手动创建的,而不是由spring管理的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52502666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档