HTTP 状態管理メカニズムは、HTTP の要求と応答を使ってステートフルセッションを作成する方法を指定します。仕様については、「RFC 2965: HTTP State Management Mechanism」(http://www.ietf.org/rfc/rfc2965.txt?number=2965) を参照してください。
Tiger 以前、Cookie 管理をアプリケーションに追加することは可能でした。ただし、API のサポートはやや不十分で、Cookie 管理につながる点はまったくありませんでした。各アプリケーションでは、java.net.URLConnection クラスから次の 2 つのメソッドを使用して、各 HTTP 要求/応答の Cookie を個別に処理する必要がありました。
setRequestProperty()
getHeaderFields()
1 つ目のメソッドは、HTTP 要求の送信前に呼び出す必要があります。これは、HTTP ヘッダーの現在の URL に適した Cookie を設定するためです。2 つ目のメソッドは、HTTP サーバーにより送信された応答ヘッダーから Cookie を取得するために使用します。
この方法で Cookie サポートを追加することは可能ですが、コードが断片化されることになります。これはエラーが発生しやすく、保守が大変です。
abstract クラスを使用した新しいコールバックメカニズムを導入しました。これは、HTTP 状態管理ポリシーの実装を HTTP プロトコルハンドラに接続することを目的としたものです。アプリケーションや Web コンテナでは、新しい API の具象サブクラスを用意すれば Cookie 管理の導入が可能です。
この新しい abstract クラスは java.net.CookieHandler と呼ばれ、これには、JVM の現在の CookieHandler の登録や取得を行うメカニズムに加えて、特定 URI に対応する Cookie の取得や記録を行うためのメソッドが用意されています。
CookieHandler には、getDefault() および setDefault() の 2 つの static メソッドが含まれています。これは、VM においてデフォルトの CookieHandler の取得や登録を行うためのものです。さらに、Cookie リストを返すための 2 つのインスタンスメソッド、get() と put() は、URL をベースとし、それぞれ応答ヘッダーから Cookie リストを保存します。
Cookie は、Map<String,List<String>> として表されます。つまり、Cookie のヘッダーフィールド名から、String によって表される一連のリストまでの Map です。これまでに定義された「Set-Cookie2」と「Cookie」の 2 つの状態管理ヘッダーが用意されています。前者は応答ヘッダーで Cookie を返す場合に使用し、後者は HTTP 要求ヘッダーで Cookie の設定を行う場合に使用します。
RFC2965 からの例を次に示します。
1. ユーザーエージェント -> サーバー
POST /acme/login HTTP/1.1
[form data]
2. サーバー -> ユーザーエージェント
HTTP/1.1 200 OK
Set-Cookie2:Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
3. ユーザーエージェント -> サーバー
POST /acme/pickitem HTTP/1.1
Cookie:$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
[form data]
次に、CookieHandler 実装の簡単な例を示します。基本的に 2 つのメソッドが用意されています。これらのメソッドでは、所定の要求 URI と要求ヘッダー (Cookie ヘッダーを除く) を実装し、Cookie キャッシュから関連する Cookie をすべて取得し、要求 URI と要求ヘッダーが与えられた Cookie キャッシュに対して適切な Cookie を記録します。
class MyCookieHandler extends CookieHandler { public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException { // the cookies will be included in request Map<String, List<String>> map = new HashMap<String, List<String>>(); List<String> l = retrieveCookies(uri, rqstHdrs); map.put("Cookie",l); return Collections.unmodifiableMap(map); } public void put(URI uri, Map responseHeaders) throws IOException { // check response has cookies[1] List l = (List)responseHeaders.get("Set-Cookie2"); if (l != null) { // save the cookies in a cookie cache storeCookies(uri, l); } } }
retrieveCookies()
と storeCookies()
の各メソッドは、この例では省略されているバックエンドの Cookie 管理機能と対話するための「マジック」機能です。
この機能が VM に登録されると、HTTP トランザクションを発行する時点で有効になります。
public static void main(String args[]) throws Exception { ...... CookieHandler.setDefault(new MyCookieHandler()); HttpURLConnection http = (HttpURLConnection)url.openConnection(); int respCode = http.getResponseCode(); http.disconnect(); ...... }
J2SE には、Cookie マネージャーのデフォルトの実装が存在しません。しかし、この点は将来変更される可能性があります。Java Plug-in と Java WebStart では、それぞれの環境においてデフォルトの CookieHandler を提供します。