【发布时间】:2015-08-03 22:04:04
【问题描述】:
我有一个休息服务,它应该验证一些东西并在另一个服务上调用 @Async 方法。就像这样:
@RestController
public class MyRest {
@Autowired
private MyService myService;
@RequestMapping(value = "/rest/do-stuff", method = RequestMethod.GET)
public ResponseEntity<String> doStuff() {
myService.computeAndDoStuff();
return "ok thanks";
}
}
@Service
public class MyService {
@Scheduled(cron="*/5 * * * * ?")
public void doSchedule() {
System.out.println("I like to work");
}
@Async
public void computeAndDoStuff() {
if (1 < 2) {
throw new RuntimeException("Indeed");
}
System.out.println("I hope it doesn't get printed");
}
}
即使 MyService 继续工作并每 5 秒打印一次“我喜欢工作”,但当其余部分点击“/rest/do-stuff”时,它会返回一个 500 http 代码以及堆栈跟踪和“Indeed”消息.
好吧,因为我是从另一个类调用的(这里没有代理类问题),我希望我的休息会返回一个 200 http 代码和“好的谢谢”消息。我错过了什么?
以防万一,我的 dispatcher-servlet.xml 如下所示:
...
<task:scheduler id="scheduleExec" pool-size="10" />
<task:executor id="asynExec" pool-size="10" />
<task:annotation-driven executor="asynExec" scheduler="scheduleExec" proxy-target-class="true" />
...
顺便说一句,如果我在上面评论这三行,@Scheduled 将停止工作(但当然没有 @Async 工作:P)。
【问题讨论】:
-
在方法入口设置断点并查看它和请求处理程序在哪些线程上运行。
-
您是否获得了 500 http 和 Indeed?如果是这样,为什么会出乎意料?您的
computeAndDoStuff()代码就是这样做的,即throw new RuntimeException("Indeed"); -
@yarivt 是的,我的
computeAndDoStuff()代码做到了这一点,但它在@Async 方法中做到了这一点。据我了解,其余服务应该调用computeAndDoStuff(),然后立即返回“好的,谢谢”。无需等待computeAndDoStuff()做任何事情... -
@Bruno 这只是意味着代码在不同的线程上运行。尝试在计算方法的开头添加
sleep(5000),看看你是否得到“好的谢谢”(你需要返回正确的对象而不是字符串)。另外,运行调试器,看看会发生什么 -
好吧,我已经设法解决了,我的 dispatcher-servlet.xml 和 applicationContext.xml 之间存在冲突(重复配置)。修复它后,我的 rest 服务开始返回 200 个 http 代码,正如我所料,即使我的 @Async 方法中抛出了异常。
标签: java spring spring-mvc asynchronous