我想从控制器内部启动异步任务,如以下Spring文档中的代码片段。
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
private class MessagePrinterTask implements Runnable {
private int cn;
public MessagePrinterTask() {
}
public void run() {
//dummy code
for (int i = 0; i < 10; i++) {
cn = i;
}
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
taskExecutor.execute(new MessagePrinterTask());
}
}
之后在另一个请求中(在任务正在运行的情况下)我需要检查任务的进度。 Basicaly获得cn的值。
Spring MVC中最好的方法是如何避免同步问题。
谢谢
PepaProcházka
答案 0 :(得分:16)
您是否查看了Spring reference doc中的@Async
注释?
首先,为异步任务创建一个bean:
@Service
public class AsyncServiceBean implements ServiceBean {
private AtomicInteger cn;
@Async
public void doSomething() {
// triggers the async task, which updates the cn status accordingly
}
public Integer getCn() {
return cn.get();
}
}
接下来,从控制器调用它:
@Controller
public class YourController {
private final ServiceBean bean;
@Autowired
YourController(ServiceBean bean) {
this.bean = bean;
}
@RequestMapping(value = "/trigger")
void triggerAsyncJob() {
bean.doSomething();
}
@RequestMapping(value = "/status")
@ResponseBody
Map<String, Integer> fetchStatus() {
return Collections.singletonMap("cn", bean.getCn());
}
}
请记住configure相应的遗嘱执行人,例如
<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5"/>
答案 1 :(得分:2)
一种解决方案可能是:在您的异步线程中,写入数据库,并让您的检查代码检查数据库表以获取进度。您可以获得持久性能数据的额外好处,以便以后进行评估。
此外,只需使用@Async
注释启动异步线程 - 让生活更轻松,并且是一种弹簧方式。
答案 2 :(得分:0)
忽略同步问题,您可以执行以下操作:
private class MessagePrinterTask implements Runnable {
private int cn;
public int getCN() {
return cn;
}
...
}
public class TaskExecutorExample {
MessagePrinterTask printerTask;
public void printMessages() {
printerTask = new MessagePrinterTask();
taskExecutor.execute(printerTask);
}
...
}
答案 3 :(得分:0)
检查此github源代码,它提供了使用Spring mvc的@Async捕获后台作业状态的非常简单的方法。
https://github.com/frenos/spring-mvc-async-progress/tree/master/src/main/java/de/codepotion/examples/asyncExample