在JAX-RS 2中编写异步端点通常如下所示:
@GET
public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
new Thread(new Runnable() {
@Override
public void run() {
String result = veryExpensiveOperation();
asyncResponse.resume(result);
}
private String veryExpensiveOperation() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// ignore
}
return "DONE";
}
}).start();
}
但是,这种方法不是很好,因为它不是声明性的。我在一些JAX-RS应用程序中看到可以使用Google Guava并编写如下代码:
ListeningExecutorService executor = ...;
@GET
public ListenableFuture<String> asyncGet() {
return executor.submit(new Callable<String>() {
@Override
public String call() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// ignore
}
return "DONE";
}
});
}
但是,我不知道如何设置JAX-RS 2实现来接受这种端点,而且我还没有弄清楚其他实现是如何做到的。
我如何配置,例如泽西岛接受这种异步声明?
答案 0 :(得分:1)
恢复FutureCallback中的asyncRresponse
:
@GET
@Produces(MediaType.TEXT_PLAIN)
public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
ListenableFuture<String> future = asyncGet();
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
asyncResponse.resume(result);
}
@Override
public void onFailure(Throwable exception) {
asyncResponse.resume(exception);
}
});
}
确保在web.xml
:
<servlet>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
...
<async-supported>true</async-supported>
</servlet>
并且您使用servlet 3.0 API。
答案 1 :(得分:0)
我不知道如何做你想做的事情,但更清晰的解决方案是创建一个通用的回调类:
class GenericFutureCallback<T> implements ListenableFutureCallback<T> {
private AsyncResponse asyncResponse;
private Response.Status status;
public GenericFutureCallback(AsyncResponse asyncResponse, Response.Status status) {
this.asyncResponse = asyncResponse;
this.status = status;
}
@Override
public void onFailure(Throwable ex) {
asyncResponse.resume(ex);
}
@Override
public void onSuccess(T result) {
Response response = Response.status(status).entity(result).build();
asyncResponse.resume(response);
}
}
然后你的控制器看起来像这样:
@GET
@Produces(MediaType.TEXT_PLAIN)
public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
ListenableFuture<String> future = asyncGet();
GenericFutureCallback<String> callback = new GenericFutureCallback<String>(asyncRes, Response.Status.OK);
Futures.addCallback(future, callback);
}