JavaのHTTPクライアントはどれがいいのか？

# 議題
JavaでHTTP通信を書くことになったけれど、クライアントライブラリはいったいどれを使うのが良いのか？
候補が多くて迷った。

# 前提条件
* 簡単に導入してサクッと使いたい
* 分かりやすくてシンプルなコードにしたい
* そんなにたくさん機能はいらない
* Androidでも使えるといい

# 何があるか

使ったことがあるもの、知っているもの

* Apache Commons HttpClient > 昔よく使った古株の有名どころ。情報が多い。
* Apache HttpComponents > 上記の発展系
* OkHttp > 最近Androidアプリで使った
* google-http-java-client > 使ったことないけどそこそこメジャーっぽい
* HttpURLConnectionで自前実装 > 昔実装したけど結構めんどい

# 他にもないか探す
Googleで「okhttp vs」や「apache httpclient vs」の検索候補で出てくるやつをリストアップ

* Google Volley https://github.com/google/volley
* ion https://github.com/koush/ion
* Loopj http://loopj.com/android-async-http/
* Unirest http://unirest.io/
* Jersey https://jersey.java.net/
* Netty https://netty.io/
* Retrofit http://square.github.io/retrofit/

ものによってはHttpClientだけでなく、JSONパースなど色んな機能を含んでいる。
探せばもっとありそう。

# 世論調査

### Uさんの選択
アーリーアダプターな仕事仲間のUさんは、最近手がけたアプリでOkHttpを使っていた。

### ネットの記事（日本人）

1. http://qiita.com/Reyurnible/items/33049c293c70bd9924ee
→ 2016-12-09 Retrofit推し

2. http://kikutaro777.hatenablog.com/entry/2015/07/19/044634
→ 2015-07-19 Unirest使ってみた

3. http://vividcode.hatenablog.com/entry/java/google-http-java-client
→ 2014-11-08 google-http-java-client使ってみた

4. http://qiita.com/kou_hon/items/ddfb3fcb0277103e8b03
→VolleyからOkHttpに乗り換え

比較記事じゃないのでジャッジしづらいが、それぞれの雰囲気は伝わる。
4によるとVolleyをAndroidで使うのは厳しそう。

### ネットの記事（海外）

1. http://stackoverflow.com/questions/1322335/what-is-the-best-java-library-to-use-for-http-post-get-etc
→2009 Commons HttpClientイチ推し。ただ7年前の記事なので古い。

2. https://www.quora.com/What-is-the-best-both-fast-and-reliable-HTTP-client-library-in-Java
→2014-2015 Unirest、Jersey、Netty、OkHttpなど推し。ばらけ過ぎて参考にならない。

# 選別方針
* 前提条件に合う
* 新しいものの方が進化してるはず
* ユーザーが多いほうが情報が多く、将来性もある

# ざっくり切り捨てる
* Apache Commons HttpClient > 古い
* Apache HttpComponents > 古い
* HttpURLConnection > めんどい
* Google Volley > ディス記事をいくつか見た
* ion > 「もしかして イオン http」って出るくらいマイナー
* Netty > ライブラリというかフレームワークなので仰々しすぎる
* Loopj > あまり情報がない。マイナーすぎ
* Retrofit > 良さげだが、OkHttpを使うし今回の趣旨から少しずれる

# ここまでの印象
残ったライブラリたち。

* OkHttp > 本命
* google-http-java-client > 対抗馬
* Unirest > ダークホース
* Jersey > 謎の黒幕

# vs でググる
google-http-java-client vs OkHttp
→ 情報が見つからない。

Unirest vs OkHttp
→ https://android.libhunt.com/project/unirest-java/vs/okhttp 知名度は圧倒的にOkHttp

OkHttp vs Jersey
→ 情報がつからない。

# ユーザー数比較
記事の多さなどから、なんとなくOkHttp一番ユーザー多そう。
Jerseyは一般的な言葉（ジャージ）なのでググりづらく謎。

# コード比較
よくある機能でコードを比較する。
ヘッダーとボディを設定してPOSTするサンプル。

### OkHttp
```java
OkHttpClient client = new OkHttpClient();
MediaType MIMEType= MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create (MIMEType,"{}");
Request request = new Request.Builder().url(url).post(requestBody).build();
Response response = client.newCall(request).execute();
```
オブジェクト作りすぎでちょっと読みづらい。

### google-http-java-client
```java
Response response =
    client
    .preparePost("http://localhost:8080/post")
    .setBody(builder.toString())
    .execute()
    .get();
```
メソッドチェーンでスッキリしているが、POSTなのに最後get()なのが勘違いしそう。

### Unirest
```java
HttpResponse<JsonNode> jsonResponse = Unirest.post("http://localhost:8080/post")
  .header("Content-Type", "application/json")
  .queryString("apiKey", "123")
  .field("param1",  "nitori")
  .field("param2", "1234")
  .asJson();
```
こちらもメソッドチェーン。特に突っ込みどころはない。

### Jersey
```java
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/post").path("resource");
 
Form form = new Form();
form.param("x", "foo");
form.param("y", "bar");
 
MyJAXBBean bean =
target.request(MediaType.APPLICATION_JSON_TYPE)
    .post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE),
        MyJAXBBean.class);
```

※[公式のサンプル](https://jersey.github.io/documentation/latest/client.html#client.ex.formpost)そのまま

# 結論
ユーザー数が多くデファクトスタンダード的なポジションを築いているOkHttpが一番無難。
マイナーであることに目をつぶれば、コード的にはUnirestが一番使い勝手がよく綺麗に実装できそう。

# さらなる何か
より突っ込んだ要件だと、パフォーマンス、Cookie管理、リトライ、マルチスレッドなど、色々考察する必要がある。

# おまけ
Java9 で標準ライブラリにHttpClientが用意されるとかされないとか。
https://thoughtfulsoftware.wordpress.com/2016/09/12/java-9-the-new-httpclient/
でもまだAndroidでは使えない。