1

我有一个带有路由器端点的 Vertx 应用程序:

router.route(HttpMethod.GET, Constants.ENDPOINT).blockingHandler(this::getItems);

这个路由器调用一个方法,它应该在浏览器中返回一个 JSON 对象,或者任何客户端调用这个端点。JSON 对象实际上来自完全不同的服务。我正在使用 Vert.x 的WebClient库来调用此服务。

    private void getItems(RoutingContext routingContext) {
    HttpServerResponse response = routingContext.response();
    response.setChunked(true);
    response.putHeader("content-type", "text/plain");
    response.putHeader("Access-Control-Allow-Origin", "*");
    JsonObject data = new JsonObject();
    WebClient webClient = WebClient.create(vertx);
    webClient.post(80, "my-site.com", "/api/items")
        .as(BodyCodec.jsonArray())
        .putHeader("Accept", "application/json")
        .putHeader("Content-Type", "application/json")
        .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
            if (ar.succeeded()) {
                HttpResponse<JsonArray> result = ar.result();
                JsonArray body = result.body();
                System.out.println(body);
                data.put("data", body.getJsonObject(0));
            } else {
                data.put("data", ar.cause().getMessage());
            }
        }); 
    response.write(data.encode());
    routingContext.response().end();
}

我从中获得的数据my-site.com很好,并使用我的 System.out 命令显示在控制台中。问题是我无法进入response.write.

阅读起来,我看到这与期货有关。我不太了解这个概念,所以我一直在阅读大量内容,但找不到任何适合我的特定代码的示例。

我将如何实现期货,以便将我收到的数据my-site.com放入我的 Json 对象(data)中,然后可以用于response.write

4

2 回答 2

2

在您的 impl 中,数据将是一个空的 JSON 对象,因为 Webclient 是异步的。在 Webclient 的响应准备好之前,您正在向客户端写入响应。

将写入移动到 webclient 响应中并在那里结束上下文。例如:

...

if (ar.succeeded()) { 
    HttpResponse<JsonArray> result = ar.result();
    JsonArray body = result.body();
    System.out.println(body); 
    data.put("data", body.getJsonObject(0));
} else { 
    data.put("data", ar.cause().getMessage());
}

response.write(data.encode());
routingContext.response().end();

...
于 2018-08-01T19:28:49.880 回答
1

Vert.x 关于异步协调的文档非常好,并且在示例中使用了期货。这是我使用 Vert.x 期货实现它的方式:

private void getItems(RoutingContext routingContext) {
        HttpServerResponse response = routingContext.response();
        response.setChunked(true);
        response.putHeader("content-type", "text/plain");
        response.putHeader("Access-Control-Allow-Origin", "*");
        // init a future that should hold a JsonObject result
        Future<JsonObject> future = Future.future();
        JsonObject data = new JsonObject();
        WebClient webClient = WebClient.create(vertx);
        webClient.post(80, "my-site.com", "/api/items")
                .as(BodyCodec.jsonArray())
                .putHeader("Accept", "application/json")
                .putHeader("Content-Type", "application/json")
                .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
                    if (ar.succeeded()) {
                        HttpResponse<JsonArray> result = ar.result();
                        JsonArray body = result.body();
                        System.out.println(body);
                        data.put("data", body.getJsonObject(0));
                        // set future to be completed, with data object as its JsonObject result
                        future.complete(data);
                    } else {
                         data.put("data", ar.cause().getMessage());
                         future.complete(data);
                         // we can also set the future as failed and give it a Throwable
                        // future.fail(ar.cause());
                    }
                });
        // handle when the future is completed
        future.setHandler(jsonObjectAsyncResult -> {
            if(jsonObjectAsyncResult.succeeded()) {
                response.write(data.encode());
                routingContext.response().end();
            }
        });
    }
于 2018-08-03T12:33:33.627 回答