JavaのHttpClientでの非同期HTTPリクエスト

先生

Java HttpClientで非同期リクエストをマスターして、アプリのパフォーマンスを爆上げしよう!🚀

Java HttpClient 非同期リクエストとは

JavaのHttpClientは、HTTPリクエストを送信するための強力なライブラリです。同期的なリクエストだけでなく、非同期リクエストもサポートしており、アプリケーションの応答性を向上させることができます。非同期リクエストを使用することで、メインスレッドをブロックせずにHTTP通信を行うことができ、GUIアプリケーションやサーバーサイドアプリケーションで特に有効です。

非同期処理は、リクエストの送信とレスポンスの受信を別々のスレッドで行うことで実現されます。これにより、リクエストの送信後すぐに次の処理に進むことができ、ユーザーインターフェースのフリーズやサーバーの処理遅延を防ぐことができます。

この記事では、JavaのHttpClientを使用して非同期HTTPリクエストを送信する方法について、具体的なコード例を交えながら詳しく解説します。

HttpClient 非同期リクエストの基本

HttpClientで非同期リクエストを行うには、HttpClientのインスタンスを作成し、HttpRequestオブジェクトを構築します。その後、sendAsyncメソッドを使用してリクエストを送信します。sendAsyncメソッドは、CompletableFuture<HttpResponse>を返します。このCompletableFutureは、将来的にHTTPレスポンスが利用可能になることを表します。

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class AsyncHttpClientExample {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://www.example.com"))
                .build();
        CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
        responseFuture.thenAccept(response -> {
            System.out.println("Status code: " + response.statusCode());
            System.out.println("Body: " + response.body());
        }).join(); // ブロッキングを避けるため、必要に応じて調整
    }
}

上記の例では、https://www.example.comに対してGETリクエストを送信し、レスポンスのステータスコードとボディをコンソールに出力しています。thenAcceptメソッドは、CompletableFutureが完了した後に実行されるコールバック関数を指定するために使用されます。join()メソッドは、CompletableFutureが完了するまで現在のスレッドをブロックします。非同期処理のメリットを最大限に活かすためには、join()メソッドの使用は最小限に抑えるべきです。

エラーハンドリングも重要です。CompletableFutureのエラーハンドリングには、exceptionallyメソッドやhandleメソッドを使用できます。

非同期リクエストの応用

非同期リクエストは、複数のリクエストを並行して実行する場合に特に有効です。例えば、複数のAPIエンドポイントからデータを取得して、それらを組み合わせて表示するようなケースです。

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class MultipleAsyncRequests {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        List<URI> uris = List.of(
                URI.create("https://www.example.com"),
                URI.create("https://www.google.com"),
                URI.create("https://www.yahoo.com")
        );
        List<CompletableFuture<String>> futures = uris.stream()
                .map(uri -> HttpRequest.newBuilder(uri).build())
                .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                        .thenApply(HttpResponse::body))
                .collect(Collectors.toList());
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        allFutures.thenRun(() -> {
            List<String> results = futures.stream()
                    .map(CompletableFuture::join)
                    .collect(Collectors.toList());
            results.forEach(System.out::println);
        });
        allFutures.join();
    }
}

上記の例では、複数のURIに対して同時にHTTPリクエストを送信し、それぞれのレスポンスボディを収集しています。CompletableFuture.allOfメソッドを使用することで、全てのリクエストが完了するのを待つことができます。

参考リンク

まとめ

JavaのHttpClientを使用した非同期HTTPリクエストは、アプリケーションのパフォーマンスと応答性を向上させるための強力なツールです。sendAsyncメソッドとCompletableFutureを組み合わせることで、ノンブロッキングなHTTP通信を実現し、複数のリクエストを並行して処理することができます。エラーハンドリングを適切に行い、非同期処理のメリットを最大限に活用しましょう。