ブラウザキャッシュの制御cache-control,expires,last-modified,etag,およびプログラミング例について

4602 ワード

ブラウザのキャッシュの意味はネットワークトラフィックを減らすことであり,この目的を達成するために2つの手段が採用されている.
1、クライアントのサーバーに対する要求を減らす
ソリューションは、リソースごとに有効期限を設定することです.
クライアントがリソースを取得した後、ローカルにキャッシュされ、しばらくの間、このリソースを再表示すると、サーバに要求するのではなく、キャッシュされたコンテンツを直接取得します.これに対応したプログラミング手段は,HtppのHeaderでCache-Control:max-age=xxx(秒)またはExpires=Tue,28 Apr 2015 15:50:47 GMT(ここではGMT時間でなければならない)を指定することであり,両者が存在する場合,Cache-Controlが優先される.
2、サーバは重複したコンテンツを転送しません.
解決策は、サーバが各リソースにタグ(またはタイムスタンプ)を付けることです.
これらのタグはリソースとともにクライアントに送信され、クライアントはリクエスト時にキャッシュにすでにこのリソースがある場合は、これらのタグをサーバに返信し、サーバはこれらのタグに基づいて再送信するかどうかを判断します.対応するプログラミング手段は
A.HtppのHeaderでLast-Modified/If-Modified-Sinceを指定し、サービス側送信リソースはLast-Modified、クライアント要求時にIf-Modified-Since、サービス側がリソースが変化していないと判断した場合、304ステータスコードに応答する.どちらもGMTタイムフォーマット
B HtppのHeaderにはETag/If-None-Martchが指定されており、サービス側送信リソースはETag付きであり、クライアント要求時にIf-None-Martchが付き、サービス側がリソースが変化していないと判断した場合、304ステータスコードに応答する.ETagは通常、リソースに対してMD 5コードを計算して得ることができる.
 
動的データや安全なデータなどのキャッシュに適していないリソースもあります.Cache-Controlにはいくつかのポリシー値があります.
No-cache:キャッシュしないで、クライアントは毎回リソースを再要求します.
Public:クライアントのISP上で確立されたプロキシサーバなど、プロキシサーバ上でキャッシュできます.
Private:クライアントでのみキャッシュでき、プロキシサーバではキャッシュできません
No-store:ファイルに保存しない
         
また、一般的ではないCach-Controlの設定もあります.例えば、
min-refresh:max-age未満で新しいリソースを要求する
max-stale:期限切れのコンテンツを受け入れることができます
また、CDNがキャッシュ・コンテンツをどのように更新するかに関するポリシー制御もあります.詳細については、http://tools.ietf.org/html/rfc2616#section-14.9を参照してください.
 
ブラウザのこれらの設定のいくつかの表現:
       
1)新しいウィンドウを開く値がprivate、no-cache、must-revalidateであれば、新しいウィンドウを開くとサーバに再アクセスします.一方、max-age値が指定されている場合、この値内の時間にサーバに再アクセスすることはありません.たとえば、Cache-control:max-age=5(このページにアクセスしてから5秒以内にサーバに再アクセスしないことを示します)
2)アドレスバーの戻り値がprivateまたはmust-revalidateの場合、最初のアクセス時のみサーバにアクセスし、以降はアクセスしません.値がno-cacheの場合、毎回アクセスします.値がmax-ageの場合、期限が切れるまでアクセスは繰り返しません.
3)後退ボタンで値をprivate、must-revalidate、max-ageとすると再アクセスせず、値をno-cacheとすると毎回繰り返しアクセスする
4)リフレッシュボタンを押すと、値に関係なくCache-control値が「no-cache」の場合、このページにアクセスしてもインターネットの一時記事にページバックアップが残されません.
また、「Expires」の値を指定することでキャッシュにも影響します.たとえば、Expiresの値が過去の時間であることを指定すると、このネットワークにアクセスするときにアドレスバーで繰り返し押すと、毎回繰り返しアクセスします:Expires:Fri、31 Dec 1999 16:00:00:00 GMT例えば、http応答メッセージヘッダ設定をIEにキャッシュするページを禁止する:CacheControl=no-cache Pragma=no-cache Expires=-1 Expiresは良い東であり、サーバ上のページが常に変化している場合は-1に設定します.すぐに期限が切れます.  
         
最後にjava web環境でプログラミングして、純粋なservletで解決すればいいです.
//       
public class ImageThumbnailServlet extends HttpServlet {

    public static final int SECOND_OF_ONE_DAY = 86400;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uniq = getSourceName(req); //  request            
        contentType="image/jpeg";


        String etag=getETag(uniq);  //     ETag
        String ifNoneMatch = req.getHeader("If-None-Match");
        if(ifNoneMatch!=null && etag.indexOf(ifNoneMatch)!=-1{  //ETag         304
                resp.reset();
                resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                return;
        }

        FileInputStream fileInputSream = getFileInputSream(uniq); //     
        try {
            Long lastModified=getLastModified(uniq);
            Long expires=calcExpires();
            Long maxAge=calcMaxAge();
            resp.setHeader("Content-Type", contentType);
            resp.setHeader("Cache-Control","public,max-age="+maxAge);
            resp.addDateHeader("Expires", expires);
            resp.addDateHeader("Last-Modified",lastModified);
            resp.addHeader("ETag",etag);

            //   
            byte[] buffer = new byte[1024];
            int byteread;
            while ((byteread = fileInputSream.read(buffer)) != -1) {
                resp.getOutputStream().write(buffer, 0, byteread);
            }
        }finally {
            fileInputSream.close();
        }
    }

    //        if-modified-since,        ,    
    @Override
    protected long getLastModified(HttpServletRequest req) {
         String uniq = getSourceName(req); //  request            
         return getLastModified(uniq);
    }

    .......
}