PR

 では、このメソッドをコールするコードを書いてみましょう。

リスト4●loadImageメソッドの使用例

HttpClient client = HttpClient.newBuilder()
                              .followRedirects(HttpClient.Redirect.ALWAYS)
                              .build();

IntStream.rangeClosed(1, 10)
         .mapToObj(i -> String.format("http://localhost:8084/%02d.jpg", i))
         .map(uri -> URI.create(uri))
         .forEach(uri -> loadImage(client, uri));

 ここでは、URIをストリームで作成して、loadImageメソッドをコールしています。同期のHTTP通信もCompletableFutureクラスを使用して扱うため、HTTPレスポンスに対する処理も容易に記述できるようになっているのがお分かりではないでしょうか。

複数のサービスの利用

 Googleの各種サービスやTwitterなどWeb APIを公開しているサービスが多くあります。これらのサービスを組み合わせて利用することも多いのではないでしょうか。HTTP/2 Clientを使用する場合、sendAsyncメソッドを使用すると、複数のサービスの利用も記述しやすくなります。

 例えば、A、B、Cの3つのサービスがあったとします。ここでAとBのサービスの結果を使用して、Cのサービスを利用すること考えます。いずれのサービスもGETで使用できるとします。

 これをsendAsyncメソッドを使用して記述したのがリスト5です。

リスト5●複数のWeb APIを利用する例

HttpClient client = HttpClient.newBuilder()
                              .followRedirects(HttpClient.Redirect.ALWAYS)
                              .build();

URI uriA = ...;
URI uriB = ...;

CompletableFuture<HttpResponse<String>> futureA = client.sendAsync(
    HttpRequest.newBuilder(uriA)
               .GET()
               .build(),
    HttpResponse.BodyHandler.asString()
);

CompletableFuture<HttpResponse<String>> futureB = client.sendAsync(
    HttpRequest.newBuilder(uriB)
               .GET()
               .build(),
    HttpResponse.BodyHandler.asString()
);

futureA.thenAccept(respA -> {
    futureB.thenAccept(respB -> {
         // AとBの結果を使用して、CのクエリーURIを作成する
         URI uriC = makeServiceCUri(respA.body(), respB.body());
         client.sendAsync(
            HttpRequest.newBuilder(uriC)
                       .GET()
                       .build(),
            HttpResponse.BodyHandler.asString()
         ).thenAccept(respC -> {
             // Cの結果に対して、何らかの処理を行う
         });
    });
});

 AとBの両方のレスポンスを受信すると、内側のthenAcceptメソッドのラムダ式が実行されます。その部分でCを利用するためのURIを作成し、Cに対してリクエストを送信します。ここでは、URIを作成するmakeServiceCUriメソッドがあったとします。最後に、Cのレスポンスを受信して、最終的な処理を行います。

 この例では、AとBの両方が完了した場合を記述しましたが、AとBのどちらか一方があればよいのであればCompletableFutureクラスのacceptEitherメソッドなどを使用できます。

 sendAsyncメソッドを使用すれば、HTTP/2を使用して複数の送受信を同時に行うユースケースだけではなく、複数のサービスをまとめるようなユースケースも容易に記述できるのです。