JavaでHTTPリクエストを作成する5つの方法
読む所要時間: 15 分
[ヘッダー画像クレジット: バタフライ星雲の鉄、NASA Astronomy Picture of the Day、2020年7月21日(修正版)]
HTTPリクエストの作成はモダンプログラミングのコア機能であり、新しいプログラミング言語の習得時に最初に学習したい操作の1つです。Javaプログラマーがこの操作を実行する場合、JDKのコアライブラリやサードパーティライブラリなどさまざまな方法を使用できます。この記事では、Java HTTPクライアントを使用する方法について説明します。もちろん他の方法も使用できますので、情報をお寄せいただければ幸いです。この記事では、次の内容について説明します。
Core Java:
- HttpURLConnection
- HttpClient
よく使用されるライブラリ:
- ApacheHttpClient
- OkHttp
- Retrofit
ここではNASA APIのAstronomy Picture of the Day APIをコードサンプルに使用します。このコードはすべて、GitHubのJava 11ベースのプロジェクトにあります。
Java httpリクエストの作成に使用する主要なJava API
Java 1.1以来、JDKに付属するコアライブラリにはHTTPクライアントが含まれています。Java 11では新しいクライアントが追加されました。プロジェクトに余分な依存関係を追加したくない場合は、これらのクライアントの1つを使用することをお勧めします。
Java 1.1 HttpURLConnection
まず、クラス名で頭字語を大文字にするかどうかを決めなければなりません。眼を閉じて1997年当時のことを思い出してみましょう。この年には映画「タイタニック」が大ヒットして感動の嵐を巻き起こし、スパイスガールズのアルバムがベストセラーになりましたが、間違いなく最大のニュースは、Java 1.1にHttpURLConnectionが追加されたことでしょう。 HttpURLConnectionを使用してGET
リクエストを作成し、APODデータを取得すると、次のようになります。
このコードはかなり冗長で、分かりにくいという声も聞かれます(URLを開いた後にヘッダーを設定する理由も腑に落ちません)。POST
本文やカスタムタイムアウトなどを使用し、より複雑なリクエストの作成が必要な場合は、それも可能ですが、私はこのAPIを直観的で使いやすいと思ったことは一度もありません。
では一体、HTTPUrlConnection
はどのような場合に使用するのでしょうか。古いバージョンのJavaを使用しているクライアントをサポートしており、かつ依存関係を追加できない場合は、HTTPUrlConnectionが役立ちます。このような開発者は少数派かもしれませんが、もっと古いコードベースでも使われていますので、最新のアプローチを理解するためにもぜひお読みください。
Java 11 HttpClient
HttpURLConnection
の登場から20年以上が経ち、映画「ブラックパンサー」がヒットしている頃、Java 11に新しいHTTPクライアントであるjava.net.http.HttpClient
が追加されました。これは非常に論理的なAPIであり、HTTP/2とWebsocketを処理できます。また、CompletableFuture
APIを使用して、リクエストを同期的または非同期的に作成することもできます。
私がHTTPリクエストを作成する場合は、100回のうち99回は、コード内でレスポンス本文を読みたいと思います。これが難しいライブラリは、使用したいと思いません。HttpClientではBodyHandler
を受け付けるため、HTTPレスポンスを任意のクラスに変換できます。組み込みハンドラもいくつかあります。例えばString
、バイナリデータ用のbyte[]
、行で分割するStream<String>
などです。独自のハンドラを定義することもできます。JSON解析用の組み込みBodyHandler
がないため、役に立つ場合があります。私が記述したハンドラは(こちら)はJacksonをベースとし、Javaドキュメントにある例に従って記述しました。これはAPODクラスのSupplier
を返すため、結果が必要な場合は.get()
を呼び出します。
以下の例は同期的リクエストです。
非同期的リクエストの場合は、client
とrequest
を同じ方法で作成してから.send
の代わりに.sendAsync
を呼び出します。
サードパーティのJava HTTPクライアントライブラリ
組み込みクライアントが役に立たなくても、大丈夫。プロジェクトに利用できる多くのライブラリがあります。
Apache HttpClient
Apache Software FoundationのHTTPクライアントは、長年使用されています。 このHTTPクライアントは広く使用されており、多くの高度なライブラリの基盤になっていますが、その歴史は少し複雑です。旧式の一般的なHttpClientは開発が終了しており、新バージョン(これもHttpClientクライアントと呼ばれます)はHttpComponentsプロジェクトで開発されています。HTTP/2サポートが追加されたバージョン5.0は、2020年のはじめにリリースされました。このライブラリも、同期的リクエストと非同期的リクエストをサポートしています。
全体的に、このAPIは比較的低レベルであり、多くの実装を自分で行う必要があります。次のコードは、NASA APIを呼び出す例です。使用はそれほど難しくはありませんが、本番コードで必要な多くのエラー処理をスキップしたため、Jacksonコードを追加してJSONレスポンスを解析しなければなりませんでした。また、stdoutでの警告を回避するために、ロギングフレームワークを構成する必要があります(大した作業ではありませんが少し面倒です)。とにかくコードをご覧いただきましょう。
CompletableFuture<APOD>
は、その戻り値の型によって非同期的クライアントになります。Squareはその他のアダプタも提供していますが、開発者が独自のアダプタを記述することもできます。このようなインターフェースを利用すると、クライアントと同じテスト環境を構築できるため、非常に便利です。
インターフェースの宣言後に、Retrofitに実装の作成を指示します。 この実装を使用して、特定のベースURLに対するリクエストを作成できます。これは、統合テストでのベースURLの切り替えにも便利です。クライアントの生成用コードは、次のとおりです。
API認証
インターフェースに複数のメソッドがあり、そのすべてにAPIキーが必要な場合は、ベースOkHttpClient
にHttpInterceptor
を追加してAPIキーを構成できます。カスタムクライアントをRetrofit.Builder
に追加できます。 カスタムクライアントの作成に必要なコードは、次のとおりです。
この種のJava APIは、極めてシンプルなケースを除くすべてのケースに使用できます。リモートAPIを表すクラスの構築は抽象化の好例であり、依存関係の注入に便利です。また、このようなクラスをRetrofitでカスタマイズ可能なOkHttpクライアントに基づいて作成するのも良い方法です。
その他のJava用HTTPクライアント
この記事をTwitterに投稿して以来、多くの方から、使用しているHTTPクライアントに関するコメントが寄せられました。以上の内容が本当に求めている情報でない場合は、次の提案も参照してください。
- REST Assured - RESTサービスのテスト用に設計されたHTTPクライアント。リクエスト作成に最適なインターフェースと、レスポンスに関するアサーションを行うための便利なメソッドを提供します。
- cvurl - Java 11 HttpClientのラッパーです。複雑なリクエストの作成時に発生しうる問題の解消に役立ちます。
- Feign - Retrofitと同様に、アノテーション付きのインターフェースでクラスを構築できます。Feignは非常に柔軟性が高く、複数のオプションを使用してリクエスト、メトリックス、リトライの作成と読み取りを実行できます。
- SpringのRestTemplate(同期)クライアントとWebClient(非同期)クライアント - プロジェクト全般でSpringを使用してきた場合は、そのエコシステムを継続することをお勧めします。Baeldungの比較記事を参照してください。
- MicroProfile Rest Client - アノテーション付きインターフェースモードでクラスを構築できる、もう1つのクライアントです。興味深いのは、同じインターフェースを再利用してWebサーバーも作成でき、クライアントとサーバーを適合させられるという点です。サービスと一緒にそのサービスのクライアントも構築する場合は、使用してみることをお勧めします。
まとめ
JavaのHTTPクライアントには多くの選択肢があります。単純なケースでは、組み込みのjava.net.http.HttpClient
をお勧めします。より複雑なユースケースの場合、またはより大きなアプリケーションの一部としてHTTP APIをJavaクラスとして抽象化したい場合は、RetrofitまたはFeignを参照してください。Happy hacking, I can’t wait to see what you build!