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の実装です。これは、ファイル名と応答ヘッダーを取得し、ファイル中のヘッダーを保存するとともに、同一ファイルに直接アクセスする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では、すぐに使用できるものを提供します。