在多线程Web应用程序中访问请求范围的Bean
问题内容:
场景:我们有一个在Websphere中运行的Spring托管的Web应用程序。(Spring 3.0.x,WAS
7)Webapp通过Spring的Web应用程序利用Websphere的工作管理器WorkManagerTaskExecutor
(配置为10的线程池)以执行计算密集型db读取操作。因此,基本上,有一个请求来生成10个不同的文件。要生成文档,只需db读取即可收集/处理数据。因此,我们基本上产生了10个线程来处理10个文档,最后收集了10个工作人员返回的10个文档,并将它们合并并写回给客户端一个很大的响应。我们确定的是,当10个线程正在收集/处理数据时,会进行许多类似的数据库调用。因此,我们想到的是围绕最执行的db方法创建一个Aspect以缓存响应。该方面被配置为单例,并且该方面使用的缓存被自动连接到该方面,并且将范围设置为request-
scope,以便每个请求都有自己的缓存。
问题:现在,这种方法的问题在于,当线程正在执行其数据库调用并且Aspect被插入时,我们将获得java.lang.IllegalStateException: No thread-bound request found
异常。我理解这是完全有效的,因为线程是在请求上下文之外执行的。
有没有办法解决这个问题?是否可以将具有请求范围的缓存的方面应用于这些线程调用的方法?
问题答案:
我认为您无法直接执行此操作。即使可以,这也会有些丑陋。但是,您可以生成唯一的请求标识符(甚至-
使用会话ID,但要小心使用多个选项卡),并将其传递给每个处理线程。然后,方面可以使用该ID作为缓存的键。缓存本身也将是单例,但将存在Map<String, X>
,其中String
ID是ID,X是您的缓存结果。
为了使事情更容易处理,您可以使用@Async
方法(而不是手动生成线程),并且每个@Async
方法都可以将缓存ID作为其第一个参数传递。
(当然,您的异步方法应该返回,Future<Result>
以便您可以在请求线程中收集其结果)