Invoking REST APIs Asynchronously With Quarkus
最近,我写了一篇关于如何使用Quarkus开发响应式REST API的博客。 异步开发实际端点是第一步。 但是,为了最大程度地利用响应功能,完整的代码路径应该是异步的,尤其是持久的操作,例如数据库访问和REST API调用。 本文介绍了两个选项如何与Quarkus异步调用REST API。
两种异步调用REST API的选项
这是两个选项:
问题是何时使用哪个选项。 除了让我自己回答这个问题之外,我还想谈谈Quarkus团队的反应专家Clement Escoffier。 Clement在StackOverflow上回答了这个问题:
您可以在同一应用程序中使用这两个选项,这是我在cloud-native-starter项目中包含的示例应用程序中所做的。 该示例应用程序使用了几种微服务。 Web-api服务调用了我将在下面描述的articles服务。
Eclipse Vert.x轴Web客户端
Quarkus使用Eclipse Vert.x指南描述了如何使用Vert.x客户端。 让我们看一下从web-api服务调用articles服务的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import io.vertx.axle.core.Vertx; import io.vertx.axle.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; import io.vertx.core.json.JsonObject; import io.vertx.core.json.JsonArray; import javax.annotation.PostConstruct; import java.util.concurrent.CompletableFuture; ... @Inject Vertx vertx; private WebClient client; @PostConstruct void initialize() { this.client = WebClient.create(vertx, new WebClientOptions().setDefaultHost(ARTICLES_DNS).setDefaultPort(ARTICLES_PORT).setSsl(false)); } public CompletableFuture<List<CoreArticle>> getArticlesReactiveVertxWebClient(int amount) { CompletableFuture<List<CoreArticle>> future = new CompletableFuture<>(); this.client.get("/v2/articles?amount=" + amount) .send() .toCompletableFuture() .orTimeout(MAXIMAL_DURATION, TimeUnit.MILLISECONDS) .thenAccept(resp -> { if (resp.statusCode() == 200) { List<CoreArticle> articles = this.convertJsonToCoreArticleList(resp.bodyAsJsonArray()); future.complete(articles); } else { future.completeExceptionally(new NoConnectivity()); } }) .exceptionally(throwable -> { future.completeExceptionally(new NoConnectivity()); return null; }); return future; } |
方法" get"和" send"调用HTTP请求。 我在上一篇文章中解释了为什么要使用" toCompletableFuture"和" orTimeout"。
请求完成后,必须检查HTTP状态代码并将其转换为Java异常。 如果请求成功,则响应将是io.vertx.core.json.JsonArray或io.vertx.core.json.JsonObject。 这些对象需要手动转换为Java对象,在此示例中为文章列表。
Eclipse MicroProfile REST客户端
第二个选项是使用MicroProfile REST客户端。 查阅我以前的博客《从Java Microservices调用REST API》,其中介绍了如何同步调用REST API。
MicroProfile REST客户端已扩展为也支持异步调用。 有一个OpenLiberty指南,它以异步方式描述了RESTful服务。
再次,让我们看一下代码。 首先,您需要定义要调用的服务的接口:
1 2 3 4 5 6 7 8 9 | import java.util.concurrent.CompletionStage; import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; ... @RegisterProvider(ExceptionMapperArticles.class) public interface ArticlesServiceReactive { @GET @Produces(MediaType.APPLICATION_JSON) public CompletionStage<List<CoreArticle>> getArticlesFromService(); } |
在此接口中,定义了一个异常映射器类。 此类将HTTP错误映射到Java异常(请参见代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; ... @Provider public class ExceptionMapperArticles implements ResponseExceptionMapper<InvalidArticle> { @Override public boolean handles(int status, MultivaluedMap<String, Object> headers) { return status == 204; } @Override public InvalidArticle toThrowable(Response response) { switch (response.getStatus()) { case 204: return new InvalidArticle(); } return null; } } |
为了调用REST API,可以调用普通的Java方法。 此方法的实现神奇地处理MicroProfile(请参见代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public CompletableFuture<List<CoreArticle>> getArticlesReactive(int amount) { CompletableFuture<List<CoreArticle>> future = new CompletableFuture<>(); URL apiUrl; try { apiUrl = new URL("http://" + ARTICLES_DNS +":" + ARTICLES_PORT +"/v2/articles?amount=" + amount); ArticlesServiceReactive articlesServiceReative = RestClientBuilder.newBuilder().baseUrl(apiUrl).build(ArticlesServiceReactive.class); articlesServiceReative.getArticlesFromService() .toCompletableFuture() .orTimeout(MAXIMAL_DURATION, TimeUnit.MILLISECONDS) .thenAccept((articles) -> { future.complete(articles); }) .exceptionally((throwable) -> { future.completeExceptionally(new NoConnectivity()); return null; }); } catch (MalformedURLException e) { future.completeExceptionally(new NoConnectivity()); } return future; } |
请注意,将JSON响应反序列化为文章列表是自动完成的。
总结思想
我的两分钱:如果您不是经验丰富的Rx Java开发人员,那么我将选择MicroProfile进行异步REST调用。 MicroProfile模型经过精心设计,您无需手动转换对象,并且不会阻塞。
本文的所有示例都包含在开源项目cloud-native-starter中。 签出查看运行中的代码。
本文是系列文章的一部分。 阅读本系列的其他文章以了解反应式编程: