HTTP は、通常、分散情報システムに使用され、そのシステムでは応答キャッシュの使用によりパフォーマンスが向上する場合があります。HTTP プロキシサーバーは、最近アクセスした Web リソースを通常キャッシュしますが、一方でローカルキャッシュがあった方がよいこともあります。その例として、ブラウザキャッシュがあります。
Tiger では、新しいフレームワークにより、プラットフォームまたはサードパーティーで実装した応答キャッシュメカニズムに対し、プロトコルハンドラがアクセスできるようになりました。
次に、その API を示します。
java.net パッケージに 3 つの abstract クラスを導入しています。これらは次のとおりです。
ResponseCache の具象サブクラスとは、URLConnection キャッシュ自体を表します。このようなクラスのインスタンスは、ResponseCache.setDefault() を呼び出してシステムに登録することができ、このシステムは次の目的のためにこのオブジェクトを呼び出します。
ResponseCache には、次の 2 つのメソッドが用意されています。get() では、URI と要求ヘッダーに基づき CacheResponse を返します。put() では、リソースをキャッシングする必要があるかどうかをキャッシュで判断することができます。CacheRequest を返します。
CacheRequest の具象サブクラスは、ResponseCache へのエントリの書き込みに使用されます。そのようなクラスのインスタンスは、プロトコルハンドラがリソースデータをキャッシュ内に格納する際に呼び出す OutputStream オブジェクトを提供するほか、キャッシュ格納処理の割り込みと中断を可能にする abort() メソッドも提供します。
CacheRequest クラスには、次の 2 つのメソッドが用意されています。getBody() では、要求の本体をキャッシュに書き込む際に必要なストリームを返します。abort() では、キャッシュの書き込みを中断します。
CacheResponse の具象サブクラスでは、ResponseCache からエントリを返します。そのようなクラスのインスタンスは、エンティティーボディーを返す InputStream を提供するほか、関連する応答ヘッダーを返す getHeaders() メソッドも提供します。
CacheResponse クラスには、次の 2 つのメソッドが用意されています。getBody() では、要求の本体をキャッシュから読み込む際に必要なストリームを返します。getHeaders() では、保存されているヘッダーを返します。
次の例は、単純なファイルをベースとしたキャッシュを示しています。ただし、キャッシュ用データベースなどのほかのメカニズムを使用する際には、この例が一様に実行されます。
MyCacheResponse クラスは、CacheResponse の実装です。このクラスでは、ファイル名を取得し、その名前から HTTP 応答ヘッダーおよび本体を取得します。
class MyCacheResponse extends CacheResponse { FileInputStream fis; Map<String, List<String>> headers; public MyCacheResponse(String filename) { try { fis = new FileInputStream(new File(filename)); ObjectInputStream ois = new ObjectInputStream (fis); headers = (Map<String, List<String>>) ois.readObject(); } catch (IOException ex) { // handle exception } } public InputStream getBody() throws IOException { return fis; } public Map getHeaders() throws IOException { return headers; } }
MyCacheRequest は、CacheRequest の実装です。この MyCacheRequest によりファイル名と応答ヘッダーを取得し、ファイル中のヘッダーを保存するとともに、同一ファイルに直接アクセスする OutputStream を返し、どのような応答の本体もその場所でのキャッシュが可能となります。
class MyCacheRequest extends CacheRequest { FileOutputStream fos; public MyCacheRequest(String filename, Map<String, List<String>> rspHeaders) { try { File file = new File(filename); fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(rspHeaders); } catch (Exception ex) { throw new RuntimeException(ex.getMessage()); } } public OutputStream getBody() throws IOException { return fos; } public void abort() { // we abandon the cache by close the stream, // and delete the file fos.close(); file.delete(); } }
最終的に、ResponseCache の実装に結び付けることができます。また、取得またはキャッシュしたネットワークリソースの URI をチェックし、CacheResponse または CacheRequest のいずれかの実装に関する適切なインスタンス情報を返します。この例では、キャッシュからの取得について URI が uri1 に等しい場合と、キャッシュの保存について URI が uri2 に等しい場合のみ処理を行います。ただし、さらに複雑なファイルをベースとするキャッシュの処理を行う際は、簡単に拡張可能です。
class MyResponseCache extends ResponseCache { public CacheResponse get(URI uri, String rqstMethod, Map rqstHeaders) throws IOException { // get the response from a cached file if available if (uri.equals(ParseUtil.toURI(uri1))) { return new MyCacheResponse(FNPrefix+"file1.cache"); } return null; public CacheRequest put(URI uri, URLConnection conn) throws IOException { // save cache to a file // 1. serialize headers into file2.cache // 2. write data to file2.cache if (uri.equals(ParseUtil.toURI(uri2))) { return new MyCacheRequest(OutFNPrefix+"file2.cache", conn.getHeaderFields()); } return null; } }
独自の ResponseCache 実装を開発したあとは、それを登録するだけで JVM で使用されるようになります。
public static void main(String args[]) throws Exception { ...... ResponseCache.setDefault(new MyResponseCache()); HttpURLConnection http = (HttpURLConnection)url1.openConnection(); InputStream is = null; ...... }
Java 2 Standard Edition における URLConnection キャッシュのデフォルトの実装はありません。ただし、Java Plug-in および Java WebStart では、すぐに使用できるものを提供します。