シンプルな HTTP クライアント Javaサンプル (Apache HttpComponents 4.5系を利用)

`curl` の基本機能相当の HTTP クライアントを Java プログラミングて実装したい場合に役立ちそうなサンプルをメモしておきます。
ここでは、Apache HttpComponents (4.5系) を利用して 特定の URL から HTTP GET するサンプル記述を残しておきます。

# Maven (pom.xml)

まず最初に、HTTP クライアントを実現するためのライブラリである `Apache` `HttpComponents` (4.5系) をビルドに組み込みます。 `pom.xml` ファイルの `<dependencies>` に以下の `Maven Repository` 記述を追加します。 (ビルドでの自動ダウンロードの実現のためには、インターネットに接続されている必要があります)

```xml
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
```

なお、[Maven Repos 上の HttpComponents はこちら](https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient)を参照してください。


# Java コード

`HttpComponents` が利用可能になったので、早速これを Java で利用して HTTP GET を実行するコードを記述しましょう。

```Java
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class App {
    public static final String URL =
     "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json";

    public static void main(String[] args) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            RequestConfig reqCfg = RequestConfig.custom() //
                    .setSocketTimeout(5000).setConnectTimeout(5000).build();
            HttpGet httpGet = new HttpGet(URL);
            httpGet.setConfig(reqCfg);

            try (CloseableHttpResponse httpResp = httpClient.execute(httpGet);) {
                if (httpResp.getStatusLine().getStatusCode() != 200) {
                    throw new IOException("HTTP ERROR: " //
                            + httpResp.getStatusLine().getStatusCode() + " " //
                            + httpResp.getStatusLine().getReasonPhrase());
                }

                String content = stream2String(httpResp.getEntity().getContent());
                System.err.println(content);
            }
        } catch (IOException ex) {
            System.err.println(ex.toString());
        }
    }

    /**
     * 入力ストリームを UTF-8 として文字列に変換.
     * 
     * @param inStream Input stream (UTF-8).
     * @return String Output value.
     * @throws IOException I/O Exception occurred.
     */
    private static String stream2String(InputStream inStream) //
            throws IOException {
        try (StringWriter writer = new StringWriter()) {
            try (BufferedReader reader = new BufferedReader( //
                    new InputStreamReader(new BufferedInputStream(inStream) //
                            , "UTF-8"))) {
                final char buf[] = new char[8192];
                for (;;) {
                    final int length = reader.read(buf, 0, buf.length);
                    if (length <= 0) {
                        break;
                    }
                    writer.write(buf, 0, length);
                }
            }
            writer.flush();
            return writer.toString();
        }
    }
}
```

## サンプルとして利用している URL について

* (注意) サンプルの 天気予報取得で利用している URL はあくまでもサンプルとして記述しているだけのものです。
    * この URL の詳細については、気象庁の意向など確認ください。
    * 地域コードは https://www.jma.go.jp/bosai/common/const/area.json から導出できます。

# 文書情報

* 初出: 2021-11-15

## 関連情報

* [シンプルな JSON 読み込み Java サンプル (jackson-databind 利用)](https://qiita.com/igapyon/items/14c6ff9430c5d8727e91)
* [シンプルな JSON 書き出し Java サンプル (jackson-databind 利用)](https://qiita.com/igapyon/items/384b88d364e0d241f91b)
* [シンプルな HTTP クライアント Javaサンプル (Apache HttpComponents 4.5系を利用)](https://qiita.com/igapyon/items/b0f9918db992c308949b)
* [シンプルな CSV ファイル書き出し Javaサンプル (Apache commons-csv を利用)](https://qiita.com/igapyon/items/7972e5dd899ec9ced776)
* [シンプルな CSV ファイル読み込み Javaサンプル (Apache commons-csv を利用)](https://qiita.com/igapyon/items/e28788c3edc720922393)