我试图了解异步响应与 Jersey 一起工作的方式。我阅读了 Jersey 文档 ( https://jersey.java.net/documentation/latest/async.html ) 的第 10 章,但这对我的问题没有帮助。此外,这里对 stackoverflow 的研究并没有得到令人满意的答案(我能理解)。
我想做的与这篇文章中的一个问题 (Use http status 202 for asynchronous operations) 类似。我想使用 HTML 表单文档将一个大文件上传到服务器。请求发送到服务器后,Web 服务应立即响应状态 202 和请求完成后可以在其中找到文件的 URI。
在阅读上面的帖子后,它似乎是可能的,但遗憾的是没有提示如何在给定的情况下实现这种行为。
我编写了一个小型网络服务来测试功能:
@Path("/test/async/")
public class TestAsyncResponse {
@GET
@Path("get")
public Response asyncGet(@Suspended final AsyncResponse response) {
new Thread(new Runnable() {
@Override
public void run() {
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
System.out.println("#### thread started: "
+ df.format(new Date()) + " ####");
String result = veryExpensiveOperation();
System.out.println("#### thread finished: "
+ df.format(new Date()) + " ####");
response.resume(result);
}
private String veryExpensiveOperation() {
try {
Thread.sleep(10000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return "Woke up!";
}
}).start();
return Response.status(202).entity("Request accepted. " +
"Long running operation started")
.build();
}
}
该服务有效,但作为响应,我收到了“醒来!”等待 10 秒后的消息而不是 202 响应,这看起来合乎逻辑,因为 AsyncResponse
是处理响应的(据我了解)。
阅读文档后,我的印象是这应该会发生,因为 Jersey 对异步服务器响应所做的所有事情都是将线程从响应线程池外包给另一个线程池,以释放处理时间以对服务进行更多响应。
所以我的两个问题是:我的理解是否正确,我可以使用异步服务器响应来获得所需的行为吗?
我试图在没有 AsyncResponse
的情况下启动一个新线程,但我得到了一个 NullPointerException
,因为 Jersey 已经关闭了响应,因此关闭了 InputStream
包含文件数据。这是预期的行为吗?这篇文章 ( https://stackoverflow.com/a/17559684/1416602) 似乎表明它可能有效。
非常感谢任何回复。
问候
最佳答案
您的问题混合了两个主题。
从 HTTP 的角度来看,202 在技术上是一个完成的请求。请求的结果是 202,服务器告诉你它会在旁边做。您必须发出另一个 HTTP 请求才能获得更新的状态。
从您的应用程序的角度来看,异步意味着您将在单独的线程(或其他异步方式)中执行请求。但是,这也意味着在另一个“veryExpensiveOperation”完成之前,您不会返回结果,甚至不会返回 202。跳过这个环的全部意义在于释放调用线程。您的网络服务器数量有限,例如20 个,如果您的每个请求都花费很长时间,则所有 20 个都将挂起。使用 @Suspended 可以将执行从 Web 服务器线程转移到其他方式(在您的情况下是另一个线程)。这真的只是第一步。异步服务器背后的想法是,即使是 veryExpensiveOperation 也是以某种异步方式实现的,以便等待数据库或文件不会占用整个线程。
关于java - Jersey:异步请求后立即响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25062726/