tokuhirom's Blog

JDK9 で入るという新しい HttpClient を試してみた

jdk9 で HTTP/2 に対応した新しい HttpClient が提供される。これは待望の新機能である。

Java には標準で java.net.httpurlconnection という http client が付属しているが、低機能で、とてもじゃないが実用には耐えない。 そこで Apache HttpClient がデファクトスタンダードっぽくなっているのだが、これまたあまり使いやすくはない。。wirelog が見づらいし。。 OkHttp というクライアントライブラリもあり、これは使いやすいが、なんか apache httpclient 信者の人に導入を阻まれがち。

そんな中で、HTTP/2 に対応した http client が jdk9 ではついてくるということで、ドキュメントを読んだり、jshell で動かしたりして遊んでみた。

[12:43 PM] tokuhirom `HttpClient.create().build().request(URI.create("http://example.com/")).GET().response().body(HttpResponse.asString())` とかで GET できるのでいい感じでした!
[12:43 PM]  mattn 最後の body はなんなの
[12:44 PM]  tokuhirom response body を string として取得
[12:44 PM]   mattn 文字列で body をくれってこと?
[12:44 PM]  tokuhirom うむ。Collectors.toList() とかと同じノリだと思う
[12:44 PM]  mattn class でよかったんじゃ感
[12:45 PM]  tokuhirom うーん
[12:45 PM]                   オブジェクトじゃないと柔軟性が失われるでしょう
[12:45 PM]  mattn まぁこうしとくとあとから実装変えられるんかな
[12:46 PM]  tokuhirom body() の引数は http://download.java.net/java/jdk9/docs/api/java/net/http/HttpResponse.BodyProcessor.html なわけですが
[12:46 PM]  例えばここ、interface だから .body(parseJson(MyEntity.class)) とかできるじゃん
[12:47 PM]  mattn naru
[12:47 PM]            とにかく web client 標準になかったからよい進歩ですな。
[12:47 PM]  tokuhirom ですね
[12:47 PM]                   javadoc 読む時、いま見てるクラスの module のトップに遷移ってのができるようになったので見やすくなった
[12:48 PM]                   cookie manager とかも標準で入ってる
[12:50 PM]                   proxy ももちろん使えるし
[12:50 PM]                    http://download.java.net/java/jdk9/docs/api/javax/net/ssl/SSLParameters.html
[12:50 PM]                    SSL の設定も細かくできるようだ
[12:51 PM]                   timeout の設定が HttpClient に見つからないと思ったけどリクエスト単位かなあ
[12:53 PM]                   timeout の設定見当たらないが、timeout 時の例外はあるっぽいんだよなw
[12:53 PM]                   HttpTimeoutException はある
[12:53 PM]  mattn supplyAsync か
[12:54 PM]            CompletableFuture ってのでいけるっぽ
List<CompletableFuture<File>> futures = targets
          .stream()
          .map(target -> {
              return HttpRequest
                  .create(target)
                  .GET()
                  .responseAsync()
                  .thenCompose(response -> {
                      Path dest = Paths.get("base", target.getPath());
                      if (response.statusCode() == 200) {
                          return response.bodyAsync(asFile(dest));
                      } else {
                          return CompletableFuture.completedFuture(dest);
                      }
                  })
                  // convert Path -> File
                  .thenApply((Path dest) -> {
                      return dest.toFile();
                  });
              })
          .collect(Collectors.toList());
[12:54 PM]  もだん
[12:55 PM]  tokuhirom そうすねえ
[12:55 PM]                    async が標準で入ってますね。最近のは
[12:56 PM]                    `HttpRequest.create(uri)..timeout(TimeUnit.SECONDS, timeout)` とかでタイムアウト指定できるのか
[12:56 PM]                    使いやすいね
[12:56 PM]                    (結局ソースみたw
[12:56 PM]                    http://download.java.net/java/jdk9/docs/api/java/net/http/HttpRequest.Builder.html#timeout-java.util.concurrent.TimeUnit-long-
[12:56 PM]                    ここにあったわ
[12:57 PM]                    良いね
[12:57 PM]                    インターセプター的なのは無いっぽい
[1:01 PM]                      例えば HttpClient.Builder にデフォルトのヘッダ値を埋める、みたいな
[1:01 PM]  mattn a-
[1:01 PM]  tokuhirom 便利だけど本質的じゃない機能は入ってない。java らしくて正しいと思うけど。

個人的な予測としては Apache HttpClient はオワコンとなり OkHttp はどうかしらんけど、Retrofit 3 あたりで JDK9 ベースになる。みたいな未来が見えます。 そんな感じです。

なおログは https://soozy.arukascloud.io/ の #java より。どなたでもお気軽にご参加いただけます。