假设我在Spring MVC中使用Java 8的完整性创建了一个异步REST API。
如何在客户端调用?如果它是非阻塞的,端点在处理之前是否会返回一些内容?即
@RequestMapping("/") //GET method
public CompletableFuture<String> meth(){
thread.sleep(10000);
String result = "lol";
return CompletableFuture.completedFuture(result);
}
这是如何运作的? (上面这段代码只是我想到的随机编码)。
当我从google chrome @ localhost:3000/
发送GET请求时会发生什么?我是异步API的新手,想要一些帮助。
答案 0 :(得分:2)
不,客户不知道它是异步的。它必须正常等待结果。它只是服务器端,可以从释放工作线程来处理其他请求中获益。
答案 1 :(得分:1)
在这个版本中,它毫无意义,因为CompletableFuture.completedFuture()
会立即创建一个完整的Future。
但是,在更复杂的代码中,您可能会返回尚未完成的Future
。 Spring将不会发送响应正文,直到其他线程在complete()
上调用Future
。
为什么不使用新线程?好吧,你可以 - 但在某些情况下,它可能更有效率。例如,您可以将任务放入Executor
以由一小段线程处理。
或者您可以触发JMS消息,要求由完全独立的计算机处理请求。程序的另一部分将响应传入的JMS消息,找到相应的Future
并完成它。在另一个系统上完成工作时,不需要专用于此HTTP请求的线程处于活动状态。
很简单的例子:
@RequestMapping("/employeenames/{id}")
public CompletableFuture<String> getName(@PathVariable String id){
CompletableFuture<String> future = new CompletableFuture<>();
database.asyncSelect(
name -> future.complete(name),
"select name from employees where id = ?",
id
);
return future;
}
我在这里为异步数据库客户端发明了一个似是而非的API:asyncSelect(Consumer<String> callback, String preparedstatement, String... parameters)
。关键是它会触发查询,然后不会阻止等待DB响应的步骤。相反,它会留下一个回调(name -> future.complete(name)
),供DB客户端在可以的时候调用。
这不是关于改进API响应时间 - 在我们提供有效负载之前,我们不会发送HTTP响应。这是关于更有效地使用服务器上的资源,以便在我们等待数据库响应时它可以做其他事情。
asynch REST有一个相关但不同的概念,其中服务器使用202 Accepted
响应并使用类似Location: /queue/12345
的标头,允许客户端轮询结果。但这不是你问的代码所做的。
答案 2 :(得分:0)
CompletableFuture
来处理复杂的异步编程。它允许程序员组合并级联异步调用,并提供静态实用程序方法runAsync
和supplyAsync来抽象出手动创建线程。
这些方法默认情况下将任务分派给Java的公共线程池,或者作为可选参数提供自定义线程池。
如果端点方法返回CompletableFuture且从未调用#complete,则请求将一直挂起,直到超时为止。