「Javaで外部APIと通信したいけど、HttpClientとHttpURLConnectionのどちらを使えばいいのか」。一度は迷うところです。
HTTPクライアントとは、WebサーバーにHTTPリクエストを送り、返ってきたレスポンスを受け取るプログラム(部品)のことです。ブラウザもHTTPクライアントの一種で、Javaから外部APIを呼ぶときは、この役割を担うクラスをコード側に用意します。
HttpClient(java.net.http.HttpClient)は、Java 11から標準搭載されたHTTP通信用のクライアントです。外部ライブラリなしでGET・POST・非同期通信がこなせ、HTTP/2にも対応しています。
Java 11以降なら、まずこれを選べば問題ありません。
以下では、GETとPOSTの基本コード、タイムアウトやヘッダーの設定、sendAsync()による非同期処理、天気APIとの連携例を順に扱います。
Java 21で追加されたclose()の使い方や、HttpURLConnectionから移行するときのつまずきどころも押さえます。
この記事でわかること
- HttpClientとHttpURLConnectionの違い
- GET・POSTリクエストの基本コード
- タイムアウト・ヘッダー・リダイレクト・プロキシ・Cookieの設定
- sendAsync()とCompletableFutureによる非同期処理
- 天気API連携・JSONパースの活用例と、Java 21のclose()など利用時の注意点
PARTS LIST /目次
HttpClientとは?
HttpClientの概要と役割
HttpClientは、Java 11から標準APIとして導入された、HTTP通信を行うためのクライアントです。
HttpClientの登場で、外部ライブラリなしでモダンなHTTP通信を書けるようになりました。
HttpClientの主な役割は、指定したURLに対してHTTPリクエストを送信し、サーバーからのレスポンスを受信することです。
HTTP/1.1はもちろん、より高速なHTTP/2プロトコルにも標準で対応している点が大きな特長です。
同期処理だけでなく、ノンブロッキングI/Oを活かした非同期処理も簡単に行えます。
※ノンブロッキングI/O:データの入出力処理(I/O)が発生した際に、その処理の完了を待たずに(ブロックせずに)次の処理へ進める方式のこと。
通信の待ち時間に別の処理を進められるため、プログラム全体の処理効率が上がります。
HttpURLConnectionとの違い
Javaには以前からHttpURLConnectionというクラスがありました。ただ、設定が煩雑で、HTTP/2や非同期通信に対応していないという課題を抱えていました。
HttpClientはその後継として設計されたAPIです。主な違いは次の表のとおりです。
これからJavaでHTTP通信を書くなら、特別な理由がない限りHttpClientを使ってください。APIが使いやすく、非同期処理やHTTP/2に標準で対応しているためです。
HttpClientの基本的な使い方(GET/POST)
HttpClientでの通信は「HttpClientを作る→HttpRequestを組み立てる→送信してHttpResponseを受け取る」の3段階です。流れを図にすると次のとおりです。
レスポンスボディの受け取り方(文字列・ファイルなど)は、送信時に渡すBodyHandlersで決めます。以降では、同期のsend()を使ったGETとPOSTから見ていきます。
HttpClientの作成方法
最初に、通信の主体となるHttpClientインスタンスを生成します。最も簡単なのはnewHttpClient()を呼ぶ方法です。
import java.net.http.HttpClient;
// HttpClientのインスタンスを生成
HttpClient client = HttpClient.newHttpClient();
newHttpClient()で作ったインスタンスには、既定の設定(HTTP/2優先・リダイレクト非追従など)が適用されます。細かく設定したい場合は、ビルダーパターンで生成します。
import java.net.http.HttpClient;
import java.time.Duration;
// ビルダーを使ってHttpClientを生成
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // 使用するHTTPバージョンを指定
.connectTimeout(Duration.ofSeconds(10)) // 接続タイムアウトを10秒に設定
.build();
HttpClientインスタンスは不変でスレッドセーフです。
アプリケーション内で1つだけ生成し、複数のリクエストで使い回すと、接続を再利用できて効率的です。
GETリクエストの基本例
GETリクエストは、ウェブページやAPIから情報を取得する際に最も一般的に使われるメソッドです。
HttpClientを使ったGETリクエストは、3つのステップで完了します。
HttpRequestの作成: 送信するリクエスト情報を定義します。- リクエストの送信:
HttpClientを使ってリクエストを送信します。 HttpResponseの処理: サーバーからのレスポンスを処理します。
GitHubの公開APIからユーザー情報を取得する例です。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetExample {
public static void main(String[] args) throws Exception {
// 1. HttpClientのインスタンスを作成
HttpClient client = HttpClient.newHttpClient();
// 2. HttpRequestを作成 (GETリクエスト)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/google"))
.header("Accept", "application/vnd.github.v3+json")
.GET() // GETメソッドを指定
.build();
// 3. リクエストを送信し、レスポンスを受信
// BodyHandlers.ofString()はレスポンスボディを文字列として受け取る
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// レスポンスの情報を出力
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
}
}
HttpRequest.newBuilder()で組み立てを始め、uri()で宛先、GET()でメソッドを指定します。
client.send()を呼ぶとリクエストが送られ、結果がHttpResponseとして返ります。
実務上の注意点として、BodyHandlers.ofString()はレスポンスボディ全体を一度にメモリへ読み込みます。
数MB程度のJSON APIなら問題ありません。
ただし画像やCSVなど大きめのファイルをダウンロードする用途では、メモリを圧迫してOutOfMemoryErrorの原因になりえます。
ファイルとして直接保存したい場合はBodyHandlers.ofFile(Path.of("output.bin"))を使います。
レスポンスをストリームのままディスクへ書き出せるため、メモリ使用量を一定に抑えられます。
POSTリクエストの送信例
POSTリクエストは、サーバーにデータを送信して新しいリソースを作成するときに使います。
例えば、フォームのデータを送信したり、JSON形式のデータをAPIに送信したりする場合です。
POSTリクエストでは、どのデータを送信するかをBodyPublishersを使って指定します。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class PostExample {
public static void main(String[] args) throws Exception {
// 送信するJSONデータ
String json = "{\"name\":\"Taro Yamada\", \"job\":\"Developer\"}";
// 1. HttpClientインスタンスを作成
HttpClient client = HttpClient.newHttpClient();
// 2. HttpRequestを作成 (POSTリクエスト)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/post"))
.header("Content-Type", "application/json") // 送信するデータの種類を指定
.POST(HttpRequest.BodyPublishers.ofString(json)) // POSTメソッドとリクエストボディを指定
.build();
// 3. リクエストを送信し、レスポンスを受信
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// レスポンスの情報を出力
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
}
}
GETリクエストとの主な違いは2点です。
主な違い
POST()メソッドを使用し、引数にHttpRequest.BodyPublishers.ofString(json)を指定して送信するデータ(リクエストボディ)を渡しています。header()メソッドでContent-Typeをapplication/jsonに指定し、送信するデータがJSON形式であることをサーバーに伝えています。
APIに送るJSON文字列を手で組み立てるのがつらくなったら、オブジェクトからJSONへの変換をJavaのJSON変換|Jackson・Gson使い方比較で確認してください。
HttpClientのオプション設定
HttpClientは、通信に関するさまざまなオプションを柔軟に設定できます。よく使う5つの設定(タイムアウト・ヘッダー・リダイレクト・プロキシ・Cookie)を紹介します。
タイムアウトの設定方法
サーバーの応答が返ってこないと、プログラムはいつまでも待ち続けます。タイムアウトを設定して、待ち時間に上限を設けましょう。
HttpClientでは、接続タイムアウトを簡単に設定できます。
import java.net.http.HttpClient;
import java.time.Duration;
// 接続タイムアウトを10秒に設定
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
connectTimeout()メソッドにjava.time.Durationオブジェクトを渡します。
指定した時間内に接続が確立されなかった場合、HttpConnectTimeoutExceptionがスローされます。
なお、connectTimeout()はHttpClient生成時に接続確立までの上限を設定するものです。
個々のリクエストごとにレスポンス待ちの上限を設定したい場合は、HttpRequest.Builder側のtimeout()メソッドを使います。
両者は役割が異なるため、用途に応じて使い分けます。
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.timeout(Duration.ofSeconds(5)) // このリクエスト単体のレスポンス待ち上限
.GET()
.build();
ヘッダーの追加方法
APIキーの指定やコンテンツタイプの指定など、リクエストヘッダーはよく追加します。
HttpRequest.Builderのheader()メソッドを使えば簡単です。
import java.net.URI;
import java.net.http.HttpRequest;
// 複数のヘッダーを追加する例
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.header("X-API-KEY", "your_api_key_here") // カスタムヘッダー
.header("Accept", "application/json") // Acceptヘッダー
.build();
同じキーでheader()を複数回呼ぶと、値は上書きされずに追加されます(1つのヘッダーに複数の値が付きます)。値を置き換えたい場合はsetHeader()を使います。
複数のヘッダーをまとめて指定するなら、headers("名前1", "値1", "名前2", "値2")のように名前と値を交互に渡すheaders()が便利です。
リダイレクトの制御
リクエストしたURLが、別のURLへリダイレクトされることがあります。
ポリシーを指定しない場合のデフォルトはNEVERで、リダイレクトには追従せず3xxのレスポンスがそのまま返ります(newHttpClient()で作った場合も同じ)。
追従させたい場合は、followRedirects()でポリシーを指定します。
import java.net.http.HttpClient;
// リダイレクトポリシーを設定
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NORMAL) // HTTPS→HTTPへのダウングレード以外は追従する
.build();
// 他のポリシー
// HttpClient.Redirect.NEVER - リダイレクトに追従しない(ビルダーで未指定時のデフォルト)
// HttpClient.Redirect.ALWAYS - 常にリダイレクトに追従する
NORMALはHTTPSからHTTPへのダウングレードを除いて追従し、ALWAYSは常に追従します。通常はNORMALを選べば安全です。
プロキシ設定
社内ネットワークなど、プロキシ経由でしか外部通信ができない環境では、HttpClientにプロキシを明示的に設定する必要があります。
ProxySelectorを使うことで、リクエストごとに個別指定しなくても、クライアント全体にプロキシ設定を適用できます。
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.http.HttpClient;
// プロキシサーバーを明示的に指定
HttpClient client = HttpClient.newBuilder()
.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 8080)))
.build();
プロキシ側で認証が必要な場合は、authenticator()メソッドと組み合わせてAuthenticatorを設定します。
プロキシなしの環境をデフォルトとし、環境変数などで切り替える構成にしておくと、開発環境と本番環境の差を吸収しやすくなります。
Cookieの管理
HttpClientは、デフォルトではCookieを保持しません。
ログイン状態を維持したまま複数リクエストを送るような場合は、CookieManagerを明示的にセットしてください。
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.http.HttpClient;
// Cookieを自動保持するHttpClientを生成
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
HttpClient client = HttpClient.newBuilder()
.cookieHandler(cookieManager)
.build();
CookieManagerをセットしておくと、レスポンスのSet-Cookieヘッダーを自動で保存し、同じクライアントからの以降のリクエストに付けて送ります。
セッション管理を伴うAPIやスクレイピング用途では、実質必須の設定です。
HttpClientを使った非同期処理
HttpClientの強力な機能の一つが非同期処理です。
非同期処理を使うと、時間のかかる通信の最中も、他の処理を止めずに進められます。
sendAsync()で非同期通信を行う
非同期でリクエストを送信するには、send()の代わりにsendAsync()メソッドを使用します。
send()がHttpResponseを直接返すのに対し、sendAsync()はCompletableFuture<HttpResponse<T>>を返します。
CompletableFutureは、まだ完了していない非同期処理の結果を保持するコンテナのようなものです。
同期処理と非同期処理でプログラムの流れがどう変わるかを図にすると、次のようになります。
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 AsyncExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/"))
.build();
// 非同期でリクエストを送信
CompletableFuture<HttpResponse<String>> future =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
System.out.println("リクエストを送信しました。レスポンスを待っています...");
// レスポンスが返ってきた後の処理を定義
future.thenAccept(response -> {
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body().substring(0, 80) + "...");
});
// 非同期処理の完了を待つ (サンプルコードのため)
future.join();
}
}
sendAsync()を呼び出すと、リクエストはバックグラウンドスレッドで実行され、プログラムは即座に次の行に進みます。
画面が固まったり、他の処理が待たされたりするのを防げます。
CompletableFutureとの組み合わせ方
CompletableFutureの真価は、非同期処理の結果に対して連続的な処理を定義できる点にあります。
thenApply(): 結果を受け取り、変換して別のCompletableFutureを返す(例: レスポンスボディの文字列をJSONオブジェクトに変換する)。thenAccept(): 結果を受け取って消費する(例: 画面に表示する)。返り値はない。thenRun(): 結果に関係なく、処理完了後に特定のRunnableを実行する。exceptionally(): 例外が発生した場合の処理を定義する。
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 CompletableFutureChain {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/google"))
.build();
CompletableFuture<Void> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body) // HttpResponseからボディ(文字列)を抽出
.thenApply(body -> { // ボディを加工 (ここでは大文字に変換)
System.out.println("ボディを大文字に変換します。");
return body.toUpperCase();
})
.thenAccept(processedBody -> { // 加工後のボディをコンソールに出力
System.out.println("処理結果:");
System.out.println(processedBody.substring(0, 100) + "...");
})
.exceptionally(e -> { // エラーハンドリング
System.err.println("エラーが発生しました: " + e.getMessage());
return null;
});
System.out.println("非同期処理のチェーンを定義しました。");
// 処理の完了を待機
future.join();
}
}
メソッドチェーンでつなぐと、非同期処理の各ステップを上から順に読める形で書けます。
HttpClientの活用例
HttpClientはさまざまな場面で活用できます。ここでは、特に一般的な2つの活用例を見ていきましょう。
API通信での利用(例:天気API)
多くのWebサービスが、外部からデータを取得するためのAPIを公開しています。
ここでは、無料で利用できる気象API「Open-Meteo」を使って、東京の現在の天気を取得する例を紹介します。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class WeatherApiExample {
public static void main(String[] args) throws Exception {
// 東京の緯度経度を指定してAPIのURLを構築
String apiUrl = "https://api.open-meteo.com/v1/forecast" +
"?latitude=35.6895&longitude=139.6917¤t_weather=true";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(apiUrl))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
System.out.println("東京の現在の天気情報:");
System.out.println(response.body());
} else {
System.out.println("天気情報の取得に失敗しました。Status Code: " + response.statusCode());
}
}
}
APIの仕様に従ってURLを組み立て、GETリクエストを送信するだけで、簡単に外部サービスのデータを利用できます。
JSONレスポンスのパース(Jackson/Gson連携)
APIから返されるデータの多くはJSON形式です。
受け取ったJSON文字列をそのまま扱うのは不便なため、通常はJavaのオブジェクトに変換(パースまたはデシリアライズ)します。
この変換には、JacksonやGsonといったライブラリがよく利用されます。ここではJacksonを使った例を示します。
(build.gradleやpom.xmlにJacksonライブラリの依存関係を追加する必要があります)
まず、JSONの構造に対応するJavaクラス(POJO)を定義します。
// CurrentWeather.java
// APIレスポンスの"current_weather"部分に対応するクラス
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
// APIレスポンスには time・interval・winddirection・is_day なども含まれるため、未定義の項目は無視する
@JsonIgnoreProperties(ignoreUnknown = true)
public class CurrentWeather {
public double temperature;
public double windspeed;
public int weathercode;
}
次に、HttpClientで受け取ったレスポンスボディをJacksonでパースします。
import com.fasterxml.jackson.databind.ObjectMapper;
// (他のimport文は省略)
public class JsonParseExample {
public static void main(String[] args) throws Exception {
// (APIリクエスト部分は前の例と同じ)
String apiUrl = "..."; // 天気APIのURL
// ... request, responseの取得 ...
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String responseBody = response.body();
// JacksonのObjectMapperを生成
ObjectMapper mapper = new ObjectMapper();
// JSON文字列をパースしてJavaオブジェクトに変換
// ここではレスポンス全体から"current_weather"ノードを抽出してパース
CurrentWeather weather = mapper.readTree(responseBody)
.get("current_weather")
.traverse(mapper)
.readValueAs(CurrentWeather.class);
System.out.println("現在の気温: " + weather.temperature + "℃");
System.out.println("現在の風速: " + weather.windspeed + " km/h");
System.out.println("天気コード: " + weather.weathercode);
}
}
}
JSONライブラリと組み合わせれば、HttpClientで取得したデータをJavaのオブジェクトとして扱えます。
HttpClient利用時の注意点
HttpClientは便利ですが、利用する上で知っておくべき点がいくつかあります。
HttpClientとOkHttpはどちらを選ぶべきか
Java標準のHttpClientには外部ライブラリ不要という利点があります。
ただし実務ではOkHttpやApache HttpClient 5系が使われているプロジェクトも依然として多くあります。判断基準はシンプルです。
新規プロジェクトで外部依存を増やしたくない場合、あるいは学習コストを抑えたい場合はHttpClientで十分です。
一方、インターセプター(リクエスト/レスポンスの共通処理を差し込む仕組み)を多用する既存プロジェクトもあります。
Retrofitのような上位ライブラリと組み合わせて使う場合は、エコシステムが成熟しているOkHttpのほうが結果的に書くコード量が少なくなることが多いです。
「標準APIだから常に正解」というわけではなく、既存のチーム標準やライブラリ構成との整合性も含めて選ぶのが実務的な判断です。
バージョンと互換性(Java 11以上)
java.net.http.HttpClientは、Java 11で正式に導入されたAPIです。
そのため、Java 8やJava 10といった古いバージョンでは利用できません。プロジェクトで使用しているJavaのバージョンを必ず確認してください。
Java 21では、HttpClientがAutoCloseableを実装しました。close()などで、クライアントが持つスレッドや接続を明示的に片付けられます。
一時的に使うクライアントなら、try-with-resourcesで書くのが簡単です(Java 21以降でコンパイルできます)。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class CloseExample {
public static void main(String[] args) throws Exception {
// Java 21以降: try-with-resourcesでHttpClientを自動クローズできる
try (HttpClient client = HttpClient.newHttpClient()) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/get"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
} // ここでclose()が呼ばれ、送信済みリクエストの完了を待ってから終了する
}
}
Java 21で追加された終了用メソッドは次の5つです。
2026年時点の最新LTSであるJava 25でも、本記事のAPIはそのまま利用できます。
もし古いバージョンで同様の機能が必要な場合は、Apache HttpClientやOkHttpといった外部ライブラリを検討する必要があります。
スレッド安全性と再利用のポイント
HttpClientインスタンスは、不変(immutable)であり、スレッドセーフに設計されています。
複数のスレッドから同時に同じインスタンスを使っても、問題は起きません。
リクエストごとにHttpClient.newHttpClient()を呼び出して新しいインスタンスを生成するのは非効率です。
HttpClientは内部で接続プールなどのリソースを管理しているため、インスタンスを生成するコストは決して小さくありません。
アプリケーションの起動時にHttpClientインスタンスを一つだけ生成し、それをアプリケーション全体で共有して使い回すのがベストプラクティスです。
// アプリケーションで共有するHttpClientインスタンス
public class AppHttpClient {
public static final HttpClient INSTANCE = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
private AppHttpClient() {}
}
// 利用する側のコード
public class SomeService {
public void doSomething() throws Exception {
HttpRequest request = ...;
// 共有インスタンスを使ってリクエストを送信
HttpResponse<String> response = AppHttpClient.INSTANCE.send(request, HttpResponse.BodyHandlers.ofString());
}
}
Java 21以降でも、アプリケーション全体で使い回す共有インスタンスは、リクエストのたびにclose()しないでください。
close()は、アプリケーション終了時などクライアントを破棄するタイミングで1回呼べば十分です。
例外処理(IOException/InterruptedException)
ここまでのサンプルコードはmainメソッドにthrows Exceptionを付けて、例外を丸ごと外側へ投げていました。
学習用なら問題ありませんが、実際のアプリケーションでは例外ごとに処理を分けてください。client.send()が投げる主な検査例外は次の2種類です。
IOException: 接続失敗・タイムアウト・DNS解決エラーなど、通信経路上の問題で発生する。InterruptedException: リクエスト送信中にスレッドが割り込みを受けた場合に発生する。
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
} catch (IOException e) {
// 通信エラー:リトライやフォールバック処理を検討
System.err.println("通信に失敗しました: " + e.getMessage());
} catch (InterruptedException e) {
// 割り込み:スレッドの割り込み状態を復元してから再スロー
Thread.currentThread().interrupt();
throw new RuntimeException("リクエストが中断されました", e);
}
InterruptedExceptionをキャッチしたときに何もせず握りつぶすと、スレッドの割り込みシグナルが失われます。
Thread.currentThread().interrupt()で割り込み状態を復元しておくのが定石です。
よくある質問(FAQ)
Q1. HttpClientとHttpURLConnectionはどちらを使うべきですか?
A1. Java 11以降のプロジェクトであれば、特別な理由がない限りHttpClientを選んでください。ビルダーパターンで直感的に書け、HTTP/2や非同期処理にも標準対応しています。HttpURLConnectionは後方互換のために残っているレガシーAPIという位置づけです。
Q2. Java 8でもHttpClientは使えますか?
A2. 標準のjava.net.http.HttpClientはJava 11以降でのみ利用できます。Java 8環境で同様の機能が必要な場合は、Apache HttpClientやOkHttpといった外部ライブラリを検討してください。
Q3. GETとPOSTの実装で何が変わりますか?
A3. 基本構造は同じです。POSTではHttpRequest.Builderにheader("Content-Type", ...)でデータ種別を指定し、POST(HttpRequest.BodyPublishers.ofString(json))で送信するボディを渡す点が異なります。GETはGET()のみでボディ指定は不要です。
Q4. 非同期処理(sendAsync)はどんな場面で使うべきですか?
A4. 複数のAPIを並行して呼び出したい場合や、UIスレッドを止めたくないアプリケーションで有効です。単純なバッチ処理やCLIツールなど、順番に結果が必要な場合はsend()で同期的に書いたほうがコードがシンプルになります。
Q5. HttpClientインスタンスは毎回生成すべきですか?
A5. いいえ。HttpClientは不変でスレッドセーフなため、アプリケーション起動時に一つだけ生成し、使い回すのがベストプラクティスです。リクエストのたびに生成すると接続プールの再構築コストがかかります。
Q6. タイムアウトはどこで設定すればいいですか?
A6. 接続確立までの上限はHttpClient.Builder.connectTimeout()で設定します。個々のリクエストのレスポンス待ち上限はHttpRequest.Builder.timeout()で設定します。役割が異なるため、両方を組み合わせて使うのが安全です。
まとめ
HttpClientはJava 11から標準搭載されたHTTPクライアントで、GET/POSTの基本から非同期処理、API連携までこなせます。
2026年時点の最新LTSであるJava 25でも同じAPIがそのまま使えるため、ここで紹介したコードは長く使い回せます。
HttpClientの利点と活用場面
HttpClientの利点は明確です。
- 標準API: 外部ライブラリを追加する手間がありません。
- モダンな機能: HTTP/2や非同期処理に標準で対応しています。
- シンプルなAPI: ビルダーパターンにより、直感的で読みやすいコードを記述できます。
- 柔軟性: タイムアウトやリダイレクトなど、詳細な設定が可能です。
Web APIとの通信、マイクロサービス間の連携、Webスクレイピングなど。
現代のJavaアプリケーション開発におけるHTTP通信の場面では、HttpClientが第一の選択肢です。
途中経過は、また書きます。
| REV. | DATE | 内容 |
|---|---|---|
| 4 | 2026-10-15 | 図解を描き直し(図面のデザインにそろえた) |
| 3 | 2026-10-14 | 雰囲気だけの挿絵を外した |
| 2 | 2026-08-07 | 2026年8月時点の情報で全体を見直し |
| 1 | 2025-07-21 | 初版 |





