概要

外部 API との連携やマイクロサービス間通信など、業務システムで HTTP リクエストを送信する場面は日常的に発生します。Java 11 で追加された HttpClient は、それまでの HttpURLConnection と比べてビルダーパターンで直感的に組み立てられ、タイムアウト設定やレスポンス処理も簡潔です。ただし Java 8 環境ではこの API が使えないため、HttpURLConnection との使い分けを理解しておく必要があります。この記事では、HttpClient による GET/POST の基本パターンから、ステータスコードの判定、接続・読み取りタイムアウトの設定、Java 21 での非同期処理まで、実務で必要になるポイントを整理します。

使いどころ

外部 REST API から JSON データを取得し、業務システムのマスタ情報を更新する

決済サービスの API に POST リクエストで注文情報を送信し、レスポンスを処理する

複数の外部 API を並行して呼び出し、レスポンスを集約してダッシュボードに表示する

コード例

HttpClient で GET/POST リクエストを送信する
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Duration;
import java.io.IOException;

public class HttpClientSample {

    private static final HttpClient CLIENT = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(5))
            .build();

    public static String get(String url) throws IOException, InterruptedException {
        var request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(10))
                .header("Accept", "application/json")
                .GET()
                .build();

        var response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() < 200 || response.statusCode() >= 300) {
            throw new IOException("HTTP エラー: " + response.statusCode());
        }
        return response.body();
    }

    public static String post(String url, String jsonBody)
            throws IOException, InterruptedException {
        var request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(10))
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                .build();

        var response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() < 200 || response.statusCode() >= 300) {
            throw new IOException("HTTP エラー: " + response.statusCode());
        }
        return response.body();
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        String body = get("https://httpbin.org/get");
        System.out.println(body);

        String json = "{\"name\":\"太郎\",\"age\":25}";
        String result = post("https://httpbin.org/post", json);
        System.out.println(result);
    }
}

Java 8 / 17 / 21 の完全なサンプルコードは GitHub リポジトリ で確認できます。

Version Coverage

HttpClient のビルダーパターンと var を組み合わせて簡潔に記述できる。同期送信が基本パターン。

Java 17
// Java 17: HttpClient で GET(簡潔)
private static final HttpClient CLIENT =
    HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(5))
        .build();

var request = HttpRequest.newBuilder()
    .uri(URI.create(url))
    .timeout(Duration.ofSeconds(10))
    .header("Accept", "application/json")
    .GET().build();
var response = CLIENT.send(request,
    HttpResponse.BodyHandlers.ofString());

Library Comparison

標準 HttpClient(Java 11+)Java 11 以降の環境で HTTP 通信を行う場合。依存追加なしで簡潔に書ける。Java 8 では使えない。リトライやインターセプターは自前で実装する必要がある。
OkHttpリトライ、インターセプター、コネクションプール制御など高度な制御が必要な場合。外部依存が増える。単純な GET/POST なら標準 HttpClient で十分。
Apache HttpComponentsJava 8 環境で HttpURLConnection より扱いやすい HTTP クライアントが必要な場合。依存が大きい。Java 11 以降では標準 HttpClient のほうが軽量。

注意点

HttpClient は Java 11 以降でのみ使用可能。Java 8 環境では HttpURLConnection を使うこと

HttpClient インスタンスはスレッドセーフなので、static final で共有して使い回すのが効率的。リクエストごとに new しない

connectTimeout はサーバーへの接続確立の制限時間、request の timeout はレスポンス全体の制限時間。両方を適切に設定すること

ステータスコード 2xx 以外をエラーとして扱う場合、HttpClient は例外を投げないため自分で判定ロジックを書く必要がある

FAQ

HttpClient と HttpURLConnection はどちらを使うべきですか。

Java 11 以降であれば HttpClient を選んでください。ビルダーパターンで組み立てやすく、非同期処理もサポートしています。Java 8 環境では HttpURLConnection を使います。

リクエストにカスタムヘッダーを追加するにはどうしますか。

HttpRequest.newBuilder().header("Authorization", "Bearer xxx") のように header メソッドをチェーンします。複数ヘッダーは header を繰り返すか headers メソッドで一括指定します。

タイムアウトはどのくらいに設定すべきですか。

connectTimeout は 3〜5 秒、request の timeout は API の応答特性に応じて 10〜30 秒が目安です。バッチ処理では長めに、画面応答では短めに設定します。

関連書籍

この記事のテーマをさらに深く学びたい方へ。

※ Amazon アソシエイトリンクを含みます