对于异步编程,Jersey(JAX-RS)提供了一个ConnectionCallback
回调,它将在连接断开时执行。来自Jersey docs:
由于某些异步请求可能需要很长时间才能处理客户端 决定在响应之前终止与服务器的连接 已经恢复或在完全写入客户之前。至 处理这些用例可以使用ConnectionCallback。这个 只有在连接过早的情况下才会执行回调 在将响应写入后面时终止或丢失 客户。请注意,响应时不会调用此回调 写成功,客户端连接按预期关闭。
听起来不错,但我永远无法解决这个问题。
这里有一些代码:
@GET
@Produces(MediaType.TEXT_PLAIN)
@ManagedAsync
@Path("/poll")
public void poll(@Suspended final AsyncResponse asyncResponse) {
asyncResponse.register(new CompletionCallback() {
@Override
public void onComplete(Throwable throwable) {
logger.info("onComplete called.");
}
});
asyncResponse.register(new ConnectionCallback() {
@Override
public void onDisconnect(AsyncResponse disconnected) {
logger.info("onDisconnect called.");
}
});
asyncResponse.setTimeout(POLL_TIMEOUT_SECONDS, TimeUnit.SECONDS);
asyncResponse.setTimeoutHandler(new TimeoutHandler() {
@Override
public void handleTimeout(AsyncResponse asyncResponse) {
logger.info("handleTimeout called.");
asyncResponse.resume(Response.status(Response.Status.OK).entity("TIMEOUT").build());
}
});
}
显示的另外两个回调,CompletionCallback和TimeoutHandler,一定会好起来,但不会失败。如果达到指定的超时持续时间,则会触发TimeoutHandler。如果恢复了AsyncResponse实例,则会触发CompletionCallback。
但是,使用ConnectionCallback,我可以关闭,终止或以其他方式停止连接到上面显示的Web服务的客户端,并且ConnectionCallback永远不会被触发。
我错过了什么吗? ConnectionCallback是否在泽西实施? (它在JAX-RS规范中是可选的,但是泽西岛文档谈论它就好像已经实现了。)
任何意见都会受到赞赏。
答案 0 :(得分:4)
ConnectionCallback确实在Jersey中实现。并且' onDisconnect'也调用了回调。您可以查看泽西岛中的以下代码:
在编写响应时,如果出现IOException,则抛出这些内容。因此,为了回答您的问题,没有轮询或类似机制继续检查客户端是否已连接,而只有在编写响应时通常会发生IOException时才会调用 onDisconnect 方法。 / p>
更新1:
我还想引用你自己的问题:
"只有在连接过早的情况下才会执行此回调 在将响应写入后面时终止或丢失 客户机"
所以,除非您尝试写入该流,否则您的回调将永远不会被触发。要清楚,当没有写入响应或响应是202时,它不应该被调用,而是当连接过早地终止时它意味着被调用,而响应是写作。
我担心除非你编写一些带有某种轮询的低级网络编程,否则没有解决这个问题的方法。但我不建议你这样做。
我建议您重新考虑处理此故障的方式。