Java : HttpClient (HTTP通信) - API使用例

HttpClient (Java SE 18 & JDK 18) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。


概要

HTTPクライアント。

クラス構成

HttpClient は、Java で HTTP通信をするための中心となるクラスです。

大まかな処理の流れとしては…

  1. まずは HttpRequest を生成。
    (通信先となる URI や、POST や GET といったリクエストメソッドを指定します)
  2. HttpClient.send メソッドに HttpRequest を指定して通信開始。
  3. 結果を HttpResponse として取得。

となります。

補足

final var uri = URI.create("http://127.0.0.1:8000/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8000/ GET

final var client = HttpClient.newHttpClient();
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response); // (GET http://127.0.0.1:8000/) 200
System.out.println(response.body()); // abcd

// --- PowerShell ---
//PS R:\java-work> cat .\index.html
//abcd
//
//PS R:\java-work> jwebserver.exe -o verbose
//Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
//Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
//URL http://127.0.0.1:8000/
//127.0.0.1 - - [03/Aug/2022:15:25:38 +0900] "GET / HTTP/1.1" 200 -
//Resource requested: R:\java-work
//> Connection: Upgrade, HTTP2-Settings
//> Http2-settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
//> Host: 127.0.0.1:8000
//> Upgrade: h2c
//> User-agent: Java-http-client/18.0.1.1
//> Content-length: 0
//>
//< Date: Wed, 03 Aug 2022 06:25:38 GMT
//< Last-modified: Wed, 3 Aug 2022 06:24:48 GMT
//< Content-type: text/html
//< Content-length: 4
//<
// 非同期の例です。
final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();

final var client = HttpClient.newHttpClient();

System.out.println("-- sendAsync start --");

final var future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(response -> {
            System.out.println("thenApply");
            return response.body();
        })
        .thenAccept(body -> {
            System.out.println("thenAccept");
            System.out.println("  body : " + body);
        });

System.out.println("-- sendAsync sending ...");

future.get();

System.out.println("-- end --");

// 結果
// ↓
//-- sendAsync start --
//-- sendAsync sending ...
//thenApply
//thenAccept
//  body : abcd
//-- end --

コンストラクタ

HttpClient ()

HttpClientを作成します。

protectedです。
独自にサブクラスを作ることは少ないと思いますので、コード例は割愛します。

メソッド

abstract Optional<Authenticator> authenticator ()

このクライアントに設定されたAuthenticatorを含むOptionalを返します。

テストサーバとして Apache HTTP Server を使っています。
Basic認証用に user=abcd, password=XYZ を用意します。

テストサーバでは HTTP で通信していますが、通常は HTTPS を使ったほうがよいでしょう。

xxxx@xxxx:/var/www/html/auth-test# cat index.html
Auth OK!

xxxx@xxxx:/var/www/html/auth-test# cat .htaccess
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /var/www/test/.htpasswd
Require valid-user

xxxx@xxxx:/var/www/html/auth-test# cat /var/www/test/.htpasswd
abcd:DkUltt9UxTbcs
(user = abcd, password = XYZ)
// 認証成功の例です。
final var authenticator = new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("abcd", "XYZ".toCharArray());
    }
};

final var uri = URI.create("http://192.168.1.9/auth-test/index.html");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://192.168.1.9/auth-test/index.html GET

final var client = HttpClient.newBuilder()
        .authenticator(authenticator)
        .build();

client.authenticator().ifPresent(a -> {
    System.out.println(a == authenticator); // true
});

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

System.out.println(response); // (GET http://192.168.1.9/auth-test/index.html) 200
System.out.println(response.body()); // Auth OK!
// 認証失敗の例です。
final var uri = URI.create("http://192.168.1.9/auth-test/index.html");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://192.168.1.9/auth-test/index.html GET

final var client = HttpClient.newHttpClient();
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response); // (GET http://192.168.1.9/auth-test/index.html) 401
System.out.println(response.statusCode()); // 401

abstract Optional<Duration> connectTimeout ()

このクライアントの「接続タイムアウト時間」を含むOptionalを返します。

// タイムアウトを起こすために、jwebserver に対して意図的に HTTPS で接続します。
final var uri = URI.create("https://127.0.0.1:8000/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // https://127.0.0.1:8000/ GET

final var client = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(15))
        .build();
System.out.println(client.connectTimeout()); // Optional[PT15S]

final var startTime = System.nanoTime();

try {
    System.out.println("-- send request --");
    final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (HttpConnectTimeoutException e) {
    System.out.println(e);

    final var endTime = System.nanoTime();
    System.out.println("timeout : " + (endTime - startTime) / 1000000000.0 + " sec.");
}

// 結果
// ↓
//-- send request --
//java.net.http.HttpConnectTimeoutException: HTTP connect timed out
//timeout : 15.096826 sec.

// -- jwebserver --
//PS R:\java-work> jwebserver.exe
//Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
//Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
//URL http://127.0.0.1:8000/
final var client = HttpClient.newHttpClient();
System.out.println(client.connectTimeout()); // Optional.empty

abstract Optional<CookieHandler> cookieHandler ()

このクライアントCookieHandlerを含むOptionalを返します。

final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();

final var cookieHandler = new CookieHandler() {
    @Override
    public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) {
        System.out.println("-- cookie get --");
        System.out.println("uri : " + uri);
        System.out.println("requestHeaders : " + requestHeaders);
        return Map.of();
    }

    @Override
    public void put(URI uri, Map<String, List<String>> responseHeaders) {
        System.out.println("-- cookie put --");
        System.out.println("uri : " + uri);

        System.out.println("responseHeaders : ");
        for (final var entry : responseHeaders.entrySet()) {
            System.out.println("  " + entry.getKey() + " : " + entry.getValue());
        }
    }
};

final var client = HttpClient.newBuilder()
        .cookieHandler(cookieHandler)
        .build();

client.cookieHandler().ifPresent(handler -> {
    System.out.println("cookieHandler : " + (cookieHandler == handler));
});

final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("res : " + response);

// 結果
// ↓
//cookieHandler : true
//-- cookie get --
//uri : http://127.0.0.1:8000/
//requestHeaders : {}
//-- cookie put --
//uri : http://127.0.0.1:8000/
//responseHeaders :
//  content-length : [4]
//  content-type : [text/html]
//  date : [Thu, 08 Sep 2022 04:56:57 GMT]
//  last-modified : [Thu, 8 Sep 2022 04:42:29 GMT]
//res : (GET http://127.0.0.1:8000/) 200

// --- PowerShell ---
//PS R:\java-work> cat .\index.html
//abcd
//
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [08/Sep/2022:13:56:57 +0900] "GET / HTTP/1.1" 200 -
final var client = HttpClient.newHttpClient();
System.out.println(client.cookieHandler()); // Optional.empty

abstract Optional<Executor> executor ()

このクライアントExecutorを含むOptionalを返します。

final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();

final var executor = Executors.newSingleThreadExecutor(r -> {
    return new Thread(() -> {
        System.out.println("-- run --");
        r.run();
    });
});

try {
    final var client = HttpClient.newBuilder()
            .executor(executor)
            .build();

    client.executor().ifPresent(e -> {
        System.out.println("executor : " + (e == executor));
    });

    final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
    System.out.println("res : " + response);

} finally {
    executor.shutdown();
}

final var ret = executor.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//executor : true
//-- run --
//res : (GET http://127.0.0.1:8000/) 200
//term : true

// -- jwebserver --
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [07/Sep/2022:16:53:20 +0900] "GET / HTTP/1.1" 200 -
final var client = HttpClient.newHttpClient();
System.out.println(client.executor()); // Optional.empty

abstract HttpClient.Redirect followRedirects ()

このクライアントのフォロー・リダイレクト・ポリシーを返します。

リダイレクト用のテストサーバとして Apache HTTP Server を使っています。
http://192.168.1.9/redirect-test/src.html にアクセスすると https://example.com/ へリダイレクトします。

xxxx@xxxx:/var/www/html/redirect-test$ cat .htaccess
RewriteEngine on
RewriteRule ^src.html$ https://example.com/ [L,R=301]
// リダイレクトする例です。
final var uri = URI.create("http://192.168.1.9/redirect-test/src.html");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://192.168.1.9/redirect-test/src.html GET

final var client = HttpClient.newBuilder()
        .followRedirects(HttpClient.Redirect.NORMAL)
        .build();
System.out.println(client.followRedirects()); // NORMAL

final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET https://example.com/) 200

// Optional[(GET http://192.168.1.9/redirect-test/src.html) 301]
System.out.println(response.previousResponse());
// リダイレクトしない例です。
final var uri = URI.create("http://192.168.1.9/redirect-test/src.html");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://192.168.1.9/redirect-test/src.html GET

final var client = HttpClient.newHttpClient();
System.out.println(client.followRedirects()); // NEVER

final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://192.168.1.9/redirect-test/src.html) 301

static HttpClient.Builder newBuilder ()

新しいHttpClientビルダーを作成します。

final var client = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(15))
        .version(HttpClient.Version.HTTP_1_1)
        .build();

System.out.println(client.connectTimeout()); // Optional[PT15S]
System.out.println(client.version()); // HTTP_1_1

final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();

final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://127.0.0.1:8000/) 200

// -- jwebserver --
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [07/Sep/2022:17:12:25 +0900] "GET / HTTP/1.1" 200 -
final var client = HttpClient.newHttpClient();

System.out.println(client.connectTimeout()); // Optional.empty
System.out.println(client.version()); // HTTP_2

final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();

final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://127.0.0.1:8000/) 200

// -- jwebserver --
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [07/Sep/2022:17:12:25 +0900] "GET / HTTP/1.1" 200 -

static HttpClient newHttpClient ()

デフォルト設定を使用して新しいHttpClientを返します。

このメソッドの使用例は、newBuilder() にまとめて記載しました。
そちらのAPI使用例をご参照ください。

WebSocket.Builder newWebSocketBuilder ()

新しいWebSocketビルダー(オプションの操作)を作成します。

WebSocket のテストサーバには、下記の wscat を使っています。
https://github.com/websockets/wscat

final var client = HttpClient.newHttpClient();
final var future = client.newWebSocketBuilder()
        .buildAsync(URI.create("ws://127.0.0.1:3000/"), new WebSocket.Listener() {
            @Override
            public void onOpen(WebSocket webSocket) {
                System.out.println("-- onOpen --");
            }
        });

future.thenCompose(ws -> {
            System.out.println("sendText");
            return ws.sendText("abcd", true);
        })
        .thenCompose(ws -> {
            System.out.println("sendClose");
            return ws.sendClose(WebSocket.NORMAL_CLOSURE, "");
        })
        .get();

// 結果
// ↓
//-- onOpen --
//sendText
//sendClose

// -- wscat --
//$ wscat -l 3000
//> abcd

abstract Optional<ProxySelector> proxy ()

このクライアントに提供されたProxySelectorを含むOptionalを返します。

final var uri = URI.create("http://127.0.0.1:8000/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8000/ GET

final var proxy = ProxySelector.getDefault();

final var client = HttpClient.newBuilder()
        .proxy(proxy)
        .build();

client.proxy().ifPresent(p -> {
    System.out.println(p == proxy); // true
});

final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://127.0.0.1:8000/) 200

// -- jwebserver --
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [08/Sep/2022:14:12:37 +0900] "GET / HTTP/1.1" 200 -
final var client = HttpClient.newHttpClient();
System.out.println(client.proxy()); // Optional.empty

abstract <T> HttpResponse<T> send (HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler)

このクライアントを使用してリクエストを送信し、必要に応じてブロックしてレスポンスを取得します。

// 結果を文字列で取得する例です。

final var uri = URI.create("http://127.0.0.1:8000/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8000/ GET

final var client = HttpClient.newHttpClient();
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response); // (GET http://127.0.0.1:8000/) 200
System.out.println(response.body()); // abcd

// --- PowerShell ---
//PS R:\java-work> cat .\index.html
//abcd
//
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [07/Sep/2022:19:06:20 +0900] "GET / HTTP/1.1" 200 -
// 結果をファイルに保存する例です。

final var file = Path.of("R:", "java-work", "save.txt");
System.out.println(file); // R:\java-work\save.txt

System.out.println(Files.notExists(file)); // true

final var uri = URI.create("http://127.0.0.1:8000/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8000/ GET

final var client = HttpClient.newHttpClient();
final var response = client.send(request, HttpResponse.BodyHandlers.ofFile(file));

System.out.println(response); // (GET http://127.0.0.1:8000/) 200

System.out.println(Files.readString(file)); // abcd

abstract <T> CompletableFuture<HttpResponse<T>> sendAsync (HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler)

指定されたレスポンス本文ハンドラとともに、このクライアントを使用して、指定されたリクエストを非同期に送信します。

final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();

final var client = HttpClient.newHttpClient();

System.out.println("-- sendAsync start --");

final var future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(response -> {
            System.out.println("thenApply");
            return response.body();
        })
        .thenAccept(body -> {
            System.out.println("thenAccept");
            System.out.println("  body : " + body);
        });

System.out.println("-- sendAsync sending ...");

future.get();

System.out.println("-- end --");

// 結果
// ↓
//-- sendAsync start --
//-- sendAsync sending ...
//thenApply
//thenAccept
//  body : abcd
//-- end --

// --- PowerShell ---
//PS R:\java-work> cat .\index.html
//abcd
//
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [07/Sep/2022:19:06:20 +0900] "GET / HTTP/1.1" 200 -

abstract <T> CompletableFuture<HttpResponse<T>> sendAsync (HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, HttpResponse.PushPromiseHandler<T> pushPromiseHandler)

指定されたレスポンス本文ハンドラとともにこのクライアントを使用して、指定されたリクエストを非同期に送信し、プッシュ・プロミス・ハンドラをプッシュします。

コード例準備中です…

abstract SSLContext sslContext ()

このクライアントSSLContextを返します。

final var uri = URI.create("https://example.com/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // https://example.com/

final var client = HttpClient.newHttpClient();

System.out.println(client.sslContext().getProtocol()); // Default

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

System.out.println(response); // (GET https://example.com/) 200

abstract SSLParameters sslParameters ()

このクライアントSSLParametersのコピーを返します。

final var uri = URI.create("https://example.com/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // https://example.com/ GET

final var client = HttpClient.newHttpClient();

final var sslParams = client.sslParameters();
System.out.println(Arrays.toString(sslParams.getProtocols())); // [TLSv1.3, TLSv1.2]

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

System.out.println(response); // (GET https://example.com/) 200

abstract HttpClient.Version version ()

このクライアントの優先HTTPプロトコル・バージョンを返します。

final var uri = URI.create("http://127.0.0.1:8000/");

final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8000/ GET

final var client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_1_1)
        .build();

System.out.println(client.version()); // HTTP_1_1

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

System.out.println(response); // (GET http://127.0.0.1:8000/) 200
System.out.println(response.body()); // abcd

// --- PowerShell ---
//PS R:\java-work> cat .\index.html
//abcd
//
//PS R:\java-work> jwebserver.exe
//...
//127.0.0.1 - - [07/Sep/2022:19:06:20 +0900] "GET / HTTP/1.1" 200 -
final var client = HttpClient.newHttpClient();
System.out.println(client.version()); // HTTP_2

関連記事

ページの先頭へ