ひさびさにHttpClientを使うことになったので、ユーザガイドのチュートリアルをもとにまとめる。
原文サイト
・Jakarta Commons HttpClient Tutorial
ちなみに上の原文サイトでは、HttpClient3.0を元に解説している。
Getting Ready
HttpClientの依存関係はdependenciesに書いてある。
commons-codecとcommons-loggingが必要。
Concepts
一般的なHttpClientの使い方は以下のステップになる。
- HttpClientのインスタンスを作成する。
- メソッドにあわせた(ここではGetメソッド)インスタンスを作成する。接続するURLはメソッドのコンストラクタに与える
- メソッドを実行する
- レスポンスを読み込む
- コネクションを開放する
- レスポンスを処理する
HttpClientの接続を開放するときには、接続が再利用可能かを確認することが必要となる。
Instantiating HttpClient
引数なしのコンストラクタだと、デフォルトの値が使われる。大体の場合、これでOKな設定になっている。
HttpClient client = new HttpClient();
Creating a Method
org.apache.commons.httpclient.methodsに定義されているメソッドを利用できる。
HttpMethod method = new GetMethod("http://www.apache.org/");
Execute the Method
executeMethodを使ってメソッドを実行する。
このメソッドはサーバのステータスコードを戻り値にしている。
int statusCode = client.executeMethod(method);
executeMethodによって投げられる例外は2種類。ひとつはHttpException、もうひとつは、IOException。
例外に関する詳細はthe HttpClient exception handling guideを参考のこと。
HttpException
HttpExceptionは論理エラーを表している、この例外はリクエストが送れなかった場合や、HTTP仕様に従っていないという致命的違反のために、処理できなかった場合に発生する。通常回復できないそうだ。
IOException
IOException ( HttpExceptionのサブクラス)は転送エラーやI/Oの問題が発生した場合に発生する可能性が高い。リトライして回復する場合がある。
Method recovery
HttpClientはIOExceptionが発生する間、自動でリトライを行うことができる。デフォルトでは3回のリトライを行う。
デフォルト値は
org.apache.commons.httpclient.params.DefaultHttpParamsFactory.getDefaultParamsから呼び出されているcreateParamsで設定されていた。getDefaultParamsメソッドはシングルトンになっている。
// createParamsメソッド params.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
つまり、以下と同じことをしていることになる。
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
独自の設定に書き換えることもできる。
DefaultMethodRetryHandler retryhandler = new DefaultMethodRetryHandler(10, true); client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryhandler);
サーバで処理されている時や、レスポンスでIOExceptionが発せしたときでもリトライは可能。
リトライはGETならば安全、POSTやPUTは危険らしい。
ウェイトさせてのリトライは、HttpClient でウェイト付きリトライを行う。 by 考え得る最高を常に行うさんにいい感じのがのってます。
Read the Response
レスポンスの読み込みはReadOnly。もっともシンプルなのがByte配列での読み込み。
byte[] responseBody = method.getResponseBody();
レスポンスの読み込み方法は以下の3つがある。
- method.getResponseBody()を使ってバイト配列出の読み込む
- method.getResponseBodyAsString()を使って文字列で読み込む。デフォルトの文字エンコーディングを使ってByte[]からStringへの変換を行う。すべてのプラットフォームで使えない可能性がある
- method.getResponseBodyAsStream()を使ってstreamで読み込む。大量データの場合はこれが一番良い。読み込みが終了したらstream.close()を呼び出すこと
Release the Connection
コネクションの終了とともに、接続を再利用できるということをHttpClientに伝える必要がある。
method.releaseConnection();
接続のリリースがなければ、HttpClientは、接続を再利用するため、コネクションの解放を無期限に待つ。危険なので忘れずに。
ソースを読んでみたけど、HttpMethodを実装しているHttpMethodBaseクラスが持っているHttpConnectionクラスをCloseしているみたい。
この辺はまた調べようー。
Deal with the Repsonse
HttpClientを使えばレスポンスの処理に集中できる。
ここで注意するのは、文字エンコーディング。デフォルトだと、デフォルトの文字エンコーディングになる。
Final Source Code
これまでをまとめたソースコード。
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
import java.io.*;
public class HttpClientTutorial {
private static String url = "http://www.apache.org/";
public static void main(String[] args) {
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod(url);
// Provide custom retry handler is necessary
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// Read the response body.
byte[] responseBody = method.getResponseBody();
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
System.out.println(new String(responseBody));
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
// Release the connection.
method.releaseConnection();
}
}
}