我正在DeferredResult
Tomcat上试验Spring,我得到了疯狂的结果。是我做错了什么,还是 Spring 或 Tomcat 中存在一些错误?我的代码很简单。
@Controller
public class Test {
private DeferredResult<String> deferred;
static class DoSomethingUseful implements Runnable {
public void run() {
try { Thread.sleep(2000); } catch (InterruptedException e) { }
}
}
@RequestMapping(value="/test/start")
@ResponseBody
public synchronized DeferredResult<String> start() {
deferred = new DeferredResult<>(4000L, "timeout\n");
deferred.onTimeout(new DoSomethingUseful());
return deferred;
}
@RequestMapping(value="/test/stop")
@ResponseBody
public synchronized String stop() {
deferred.setResult("stopped\n");
return "ok\n";
}
}
所以。该start
请求创建一个DeferredResult
4 秒超时。该stop
请求将在DeferredResult
. 如果您stop
在延迟结果超时之前或之后发送,一切正常。
但是,如果您stop
在超时的同时发送start
,事情就会变得疯狂。我添加了一个onTimeout
操作以使其易于重现,但这不是问题发生所必需的。使用 APR 连接器,它只会死锁。使用 NIO 连接器,它有时可以工作,但有时它会错误地将“超时”消息发送给stop
客户端,并且永远不会回答start
客户端。
要对此进行测试:
curl http://localhost/test/start & sleep 5; curl http://localhost/test/stop
我不认为我做错了什么。Spring 文档似乎说可以随时调用setResult
,即使在请求已经过期之后,也可以从任何线程调用(“应用程序可以从它选择的线程产生结果”)。
使用的版本:Linux 上的 Tomcat 7.0.39,Spring 3.2.2。