SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Java 11の変更点と新しいAPI

Java 11の変更点を押さえよう! 標準機能になったHTTP Client API

Java 11の変更点と新しいAPI 第1回

  • X ポスト
  • このエントリーをはてなブックマークに追加

HTTP Client API

 HTTP Client APIの追加はもっとも多くの開発者にとって影響があると思われます。

 Java 9がリリースされる前にはHTTP2 Clientといった触れ込みでリリースされる予定がありましたが、Java 11までに完全に実装が書き換わり、Java 11ではHTTP2のみならず、HTTP関連のプロトコルを扱うためのClient APIとしてリリースされました。

 また、Javaで、HTTP Clientとしての機能を使う場合には標準で用意されているHttpURLConnectionクラスを利用するか、Apache HttpClientやOkHttpなどの外部ライブラリを利用するケースが多いと思います。

 しかし、HTTP Client APIはこれまでのHttpURLConnectionよりも使いやすく、また、多くのケースでは外部ライブラリを使わなくてもよいレベルになるはずです。

 特に、HttpURLConnectionに比べて、以下のメリットがあります。

  • HTTP 1.1だけではなく、HTTP 2にも対応している
  • 同期処理だけでなく、Non-Blockingでの非同期処理にも対応している
  • 外部APIを使っていた方でもわかりやすく、よりなりじみやすいAPI構造
  • WebSocket通信も可能

基本的なAPIの使い方

 最初に、APIの利用方法をイメージするため、基本的なHTTP GET/POSTの利用方法を紹介します。

 リスト5は同期処理としてHTTP GETでHTMLテキストを取得する場合の実行例です。(1)でHTTP Clientのオブジェクトを作成し、(2)でリクエストを作成、(3)でリクエストを実行といった流れになっています。

[リスト5]HTTP GETリクエスト(src/main/java/com/coltware/Java 11HttpClient.javaの抜粋)
HttpClient client = HttpClient.newHttpClient(); // (1) HTTP Clientを作成
HttpRequest getRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://codezine.jp/"))
    .build();   // (2) リクエストを作成

HttpResponse<String> response = client.send(getRequest, HttpResponse.BodyHandlers.ofString());  // (3) レスポンスを取得する
logger.log(Level.INFO,response.body());

 HttpURLConnectionなどを使った処理よりも、HTTP操作としては自然なコーディングスタイルとして利用できることがわかるはずです。

 また、リスト6はApache HTTP Clientを使った場合のHTTP GETメソッドを使った処理のコード例ですが、同様な流れで記述できることがわかります。

 従って、リプレースなどもしやすいはずです。

[リスト6]Apache HTTP Clientを使った場合のGETリクエストのコード(src/main/java/com/coltware/ApacheHttpClient.javaの抜粋)
CloseableHttpClient client = HttpClients.createDefault(); // HTTP Clientを作成
HttpGet requestGet = new HttpGet("http://localhost/get.php");  // (2) リクエストを作成
CloseableHttpResponse response = client.execute(requestGet);  //  (3) レスポンスを取得する

logger.log(System.Logger.Level.INFO,EntityUtils.toString(response.getEntity()));
response.close();

 続いて、非同期処理の場合のコード例をリスト7に示します。

 非同期処理ではHttpResponseの代わりに、(1)のように非同期でリクエストを実行すると、戻り値としてCompletableFutureが返って来ます。

 CompletableFutureはJava1.8から導入された、比較的新しいAPIです。CompletableFutureクラスの使い方は今回説明しませんが、Futureインターフェースの実装クラスで複数の非同期処理が管理しやすくなります。

 レスポンスに対する処理は(2)のようにCompletableFutureクラスのthenAcceptメソッドなどを利用し処理を行うことができます。

[リスト7]非同期でのHTTP GETリクエスト(src/main/java/com/coltware/Java 11HttpClient.javaの抜粋)
HttpClient client = HttpClient.newHttpClient();
HttpRequest getRequest = HttpRequest.newBuilder()
    .uri(URI.create("http://localhost/get.php"))
    .build();

CompletableFuture<Void> f = client.sendAsync(getRequest,HttpResponse.BodyHandlers.ofString()) // (1) 非同期リクエストの実行
    .thenAccept(response -> {    // (2) レスポンスに対する処理
        logger.log(Level.INFO,"status code : " + response.statusCode());
        logger.log(Level.INFO,"body is : " + response.body());
    });

 続いて、JSONデータをPOST処理する場合の例をリスト8に示します。(1)でPOSTするJSONデータを作成します。そして、(2)でJSONデータのコンテントタイプをヘッダにて指定し、(3)にてPOSTメソッドで送信するJSONデータを指定します。

 今までの例では、(3)のように明示的にPOSTメソッドを指定していませんでしたが、これはデフォルトでGETメソッドが指定されるためです。

[リスト8]非同期でのHTTP GETリクエスト(src/main/java/com/coltware/Java 11HttpClient.javaの抜粋)
HttpClient client = HttpClient.newHttpClient();

String json  = "{ \"key\" : \"value\" }";  // (1) POSTするJSONデータ
HttpRequest postRequest = HttpRequest.newBuilder()
    .header("Content-Type","application/json")        // (2) ヘッダの指定
    .uri(URI.create("http://localhost/post.php"))
    .POST(HttpRequest.BodyPublishers.ofString(json))  // (3) POSTメソッドを指定
    .build();

HttpResponse<String> response = client.send(postRequest, HttpResponse.BodyHandlers.ofString());
logger.log(Level.INFO,response.body());

リクエストボディとレスポンスボディの型指定

 これまで紹介したコードを見ると、sendもしくはsendAsyncメソッドでHttpResponse.BodyHandlersというクラスを使用しています。

 また、POSTメソッドではHttpRequest.BodyPublishersというクラスを使用しています。

 HTTP Client APIでは、レスポンスボディの形式をHttpResponse.BodyHandlerインターフェースを使って処理します。

 そして、HttpResponse.BodyHandlersには表1のように、よく利用するであろう実装があらかじめ用意されています。

 また、ここで紹介するメソッド以外にも用意されているので、詳細はAPIリファレンスを参照してください。

表1:レスポンスボディを取得するための主なメソッド
レスポンスボディの型 メソッド 概要 
Void  discarding() レスポンスボディを取得しない場合
byte[] ofByteArray()  byte配列として取得する場合
String ofString() 文字列として取得する場合
Stream<String> ofLines() Stream<String>(1行ごとを文字列)として取得する場合
InputStream ofInputStream() InputStreamとして取得する場合
Path ofFile​(Path file) 指定したファイルにデータを保存して取得する場合
Path ofFileDownload​(Path directory, OpenOption... openOptions) 指定したフォルダにContent-Dispositionヘッダで指定されたファイル名でデータを保存して取得する場合

 リクエストボディの形式は、HttpRequest.BodyPublisherインターフェースを使って処理します。

 こちらも、HttpRequest.BodyPublishersに、表2のようにあらかじめよく利用すると思われる実装が用意されています。

表2:リクエストボディを設定するための主なメソッド
指定するリクエストボディの型 メソッド 概要 
void noBody() 空のリクエストボディを指定する場合
byte[] ofByteArray(byte[] buf) byte配列データを指定する場合
String  ofString(String body)  文字列データを指定する場合
InputStream ofInputStream(Supplier<? extends InputStream> streamSupplier)  指定したファイルのデータを指定する場合
Path ofFile​(Path file) InputStreamとして取得する場合

 リクエストボディとレスポンスボディの処理は内部で、Java 9から導入されたリアクティブ・ストリームのFlow.PublisherやFlow.SubscriberなどのAPIを利用しています。

 従って、単純なHTTP操作ではなく、少々複雑なChunk処理や、WebSocketのようなHTTPプロトコル内で動作するプロトコルなどの処理もしやすくなるはずです。

最後に

 Java 11はLTS版の位置付けになっているので、開発者にとってもJavaサポートバージョンの1つの区切りとして意識する必要があると言えます。そのバージョンでJava EE関連のモジュールが削除されたことは、Javaとしての1つの方向性を示しているでしょう。

 また、HTTP Client APIの追加は、多くの開発者が興味を持つ変更だと思われます。現在の開発ではWebサービスと連携して機能を開発することは必須とも言え、こういったAPIが今導入されることはむしろ遅かったとも思います。

 今回のHTTP Client APIの紹介は簡単な利用例のみでしたが、次回はWebSocket通信を含めてより実用的な利用方法などを紹介します。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Java 11の変更点と新しいAPI連載記事一覧
この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/11071 2018/09/21 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング