mike-neckのブログ

Java or Groovy or Swift or Golang

Java9(ea163)でHttpClientを使ってみたノート

ディレクトリ構成やmodule-info.javaで少々ハマったので(10分)、ノート。


Java SE9から公式のやっと面倒くさくないHttp Clientが出るので試してみた。

試してみたのは jdk.incubator.httpclient モジュールの jdk.incubator.http.HttpClient とその関連クラス。

1. ディレクトリー構成

Java9からはモジュールを定義しておかないと、使いたいクラスがうまく利用できない。したがって、まずモジュール名を決定した後にモジュール名と同じ名前のディレクトリーを作り、その下に src ディレクトリーを作る。

まずモジュール名は com.example とした。

ディレクトリーを次のように作る。

root/
└── com.example
    └── src

2. モジュールの定義

src ディレクトリーの下に module-info.java を作る。ここには、公開するパッケージの定義と利用するモジュールを記入する。詳しい話は IT Proの連載記事 などを参考にした。なお、今回作るプログラムを配置するパッケージを com.example.ex とした。また、利用するモジュールは上述のとおり jdk.incubator.httpclient である。

module com.example {
  exports com.example.ex;
  requires jdk.incubator.httpclient;
}

現在のディレクトリー構成

root/
└── no.lib
    └── src
        └── module-info.java

3. プログラムを書く

適当に書く。

package com.example.ex;

import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpClientTest {

    public static void main(String[] args) {
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        final HttpClient client = HttpClient
                .newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .executor(executor)
                .followRedirects(HttpClient.Redirect.SAME_PROTOCOL)
                .build();
        final HttpRequest request = HttpRequest.newBuilder(URI.create("https://www.google.com/teapot"))
                .GET()
                .build();
        client.sendAsync(request,
                HttpResponse.BodyHandler.asString(StandardCharsets.UTF_8))
                .thenApply(HttpResponse::body)
                .thenApply(s -> String.format("[%s] - %s", Thread.currentThread().getName(), s))
                .thenAccept(System.out::println)
                .join();
        executor.shutdown();
    }
}

実行結果

WARNING: Using incubator modules: jdk.incubator.httpclient
[pool-1-thread-1] - <!doctype html><html class="google" lang="en"> <script>(function(H){H.className=H.className.replace(/\bgoogle\b/,'google-js')})(document.documentElement)</script> <meta charset="utf-8"> <meta content="initial-scale=1, minimum-scale=1, width=device-width" name="viewport"> <title>Error 418 (I&#8217;m a teapot)!?</title> <link href="//www.gstatic.com/teapot/teapot.min.css" rel="stylesheet"> <a href="//www.google.com/"><span aria-label="Google" id="logo"></span></a> <p><b>418.</b> <ins>I&#8217;m a teapot.</ins></p> <p>The requested entity body is short and stout. <ins>Tip me over and pour me out.</ins></p> <div id="teaset"><div id="teabot"></div><div id="teacup"></div></div> <script src="//www.gstatic.com/teapot/teapot.min.js"></script> </html>

Process finished with exit code 0

現在のディレクトリー構成

└── com.example
    └── src
        ├── com
        │   └── example
        │       └── ex
        │            └── HttpClientTest.java
        └── module-info.java

たまにモジュール内のパッケージの export 先が決まっていることがあったりするので、気をつけたい。