【问题标题】:How to attach async job to a HTTP session?如何将异步作业附加到 HTTP 会话?
【发布时间】:2015-07-27 15:19:26
【问题描述】:

我需要从控制器运行一些耗时的任务。为此,我在我的服务中实现了一个@Async 方法,以便控制器可以立即返回(例如202 Created 状态)。

问题是任务需要访问一些会话范围的 bean。通过这种方法,我得到了org.springframework.beans.factory.BeanCreationException: Error creating bean with name (...): Scope 'session' is not active for the current thread (...)

当我手动创建 ExecutionService 而不是 @Async 时,结果相同。

是否有可能以某种方式使工作线程附加到当前会话?


编辑 目的是实现批量操作,提供一种监控处理状态的方法。类似于此答案中描述的内容:https://stackoverflow.com/a/28787774/718590

如果我同步运行它,将不会显示状态(处理了多少项),并且可能会出现请求超时。

【问题讨论】:

  • 你能分享更多细节吗?在异步执行期间你真的需要它吗?你能事先提取所需的信息吗?或者你只需​​要像stackoverflow.com/questions/29716119/…一样在之后存储结果?
  • @sodik 我已经为问题添加了更多细节。
  • @AndreiI 我没有将线程附加到会话中。是 Spring 维护线程和会话之间的连接。

标签: java spring spring-mvc session asynchronous


【解决方案1】:

如果我理解正确,您希望能够从 Spring Web 应用程序开始长时间的异步处理,并能够从启动它的会话中跟踪处理的进展。并且处理可以使用会话中包含的 bean。

为了很好地分离关注点,我永远不会让异步线程知道会话。会话与 HTTP 相关,可以在线程完成(甚至在竞争条件下开始)其处理之前的任何时间销毁。

恕我直言,正确的设计是创建一个类,其中包含 Web 部件和异步处理之间共享的所有信息:状态(无论它是什么)、开始处理的用户是否相关以及所有其他相关一点信息。在您的控制器中(最好是在控制器调用的服务方法中)您准备该类的一个对象,并将其传递给@Async 方法。然后在返回之前,控制器将对象存储在会话中。那样:

  • 异步处理拥有所有需要的信息,即使会话稍后被销毁。它不需要知道会话,只关心它的处理和更新它的状态
  • Web 应用程序的会话知道异步处理正在运行,知道它是如何启动的以及当前状态是什么

它可以适应您的实际问题,但这应该满足您的要求。

【讨论】:

  • 嗯,建议的设计看起来不错,但需要对整个应用程序的设计进行重大更改。我不是在编写新应用程序,只是将 HTTP API 添加到现有应用程序。如果会话消失,处理失败可能是可以的 - 任务是用户启动的,即使用户注销,当前也不需要保持处理。不过,这可能是一个不错的功能。
猜你喜欢
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 2010-09-20
  • 2016-07-10
  • 2020-10-21
  • 2016-08-21
  • 2023-02-17
相关资源
最近更新 更多