3 回答
TA贡献1725条经验 获得超7个赞
问题不在于您的Spring注释,而在于您的设计模式。您将不同的作用域和线程混合在一起:
单身人士
会话(或请求)
作业线程池
单身人士可以在任何地方使用,没关系。但是,会话/请求范围在附加到请求的线程之外不可用。
即使请求或会话不再存在,异步作业也可以运行,因此无法使用依赖于请求/会话的bean。同样也没有办法知道,如果您正在另一个线程中运行作业,哪个线程是发起者请求(这意味着aop:proxy在这种情况下没有帮助)。
我觉得你的代码看起来像要作合同 ReportController,报表制作,UselessTask和ReportPage之间。有没有办法只使用一个简单的类(POJO)来存储UselessTask中的数据并在ReportController或ReportPage中读取它,而不再使用ReportBuilder?
TA贡献2039条经验 获得超7个赞
如果还有其他人坚持同一观点,以下解决了我的问题。
在web.xml中
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
会话中组件
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
在pom.xml中
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
TA贡献1799条经验 获得超6个赞
原因
原因是使用多个线程。如Spring Guide中所述,请求对象在这些线程中不可用:
DispatcherServlet,RequestContextListener并且RequestContextFilter都做同样的事情,即绑定HTTP请求对象添加到服务该请求的线程。这使得在请求链和会话范围内的bean可以在调用链的更下游使用。
解决方案1
可以使请求对象可用于其他线程,但是它对系统有一些限制,这在所有项目中可能都不可行。我从在多线程Web应用程序中访问请求范围的Bean获得了此解决方案:
我设法解决了这个问题。我开始使用SimpleAsyncTaskExecutor而不是WorkManagerTaskExecutor/ ThreadPoolExecutorFactoryBean。好处是SimpleAsyncTaskExecutor永远不会重复使用线程。那只是解决方案的一半。解决方案的另一半是使用RequestContextFilter而不是RequestContextListener。RequestContextFilter(以及DispatcherServlet)具有一个threadContextInheritable属性,该属性基本上允许子线程继承父上下文。
解决方案2
唯一的其他选择是在请求线程内使用会话范围的Bean。就我而言,这是不可能的,因为:
控制器方法用注释@Async;
控制器方法将启动批处理作业,该批处理作业将线程用于并行作业步骤。
- 3 回答
- 0 关注
- 854 浏览
添加回答
举报