2014-01-08 74 views
1

我正试图在Spring MVC应用程序中实现一个功能,该功能可以启动长时间运行的作业。该任务将由Spring Controller启动。由于可能需要很长时间才能完成(几分钟到一个多小时),@Async似乎是我尝试完成的完美人选。Spring MVC @Async限制任务

一个要求是,我想限制每个id的异步任务。解释问题陈述。假设我们需要为给定的学生ID建立学生报告。控制器将启动给定ID的报告工作。在任何给定的时间,只有一个报告可以针对给定的学生ID运行。

如果有新的请求进入,如果有一个报告正在运行该ID,我们想要取消它并开始一个新的工作(假设新的请求将提供最新的信息并且旧的请求不再相关)。报告任务可以针对不同的ID运行(例如,学生ID为100和200的作业可以运行,但是每个ID只能运行一个任务,即,不应该有两个ID100的作业)。

这里是控制器会是什么样子:

@RequestMapping("/report/{id}") 
.. ... 
Future<Void> reportFuture = reportService.generate(id) 
..... 

服务将类似于:

@Async 
public Future<Void> generate(int id) { 
... Do some Long Calculations generate a report 
} 

那么,我们怎样才能保持跟踪异步任务,例如,我们知道,如果有是为给定的ID运行的工作,如果这样取消的话?

+0

您必须将'Future'存储在具有相应ID的某个共享地图中。如果新的请求出现在同一个ID中,您可以取消未来。您可能需要通过一些中断机制来实现您的'@ Async'方法。 –

+0

谢谢@SotiriosDelimanolis,澄清,这正是我的问题的重点。什么是最好的方式来存储未来。如果我进入会话,它将仅适用于每个用户会话。可能有多个用户。 – bond

+0

你可以把它放在'ServletContext'中,或者创建一个包含它们映射的单例bean。尽管如此,你不需要内存泄漏。 –

回答

1

我最终通过创建一个可以跟踪报表的单例作用域组件来解决这个问题。在进行服务呼叫时,它将首先检查组件以查看给定ID是否有Future。如果不是,则会在该组件中添加Future并开始该过程。如果组件返回Future,它将调用Future上的取消并开始新的服务呼叫。