zoukankan      html  css  js  c++  java
  • 通过HTTP头控制浏览器的缓存

    通过HTTP头控制浏览器的缓存
           浏览器缓存是提高用户体验和提升程序性能的一个很重要的途径,通过浏览器的缓存控制,可以对实时性要求不高的数据进行缓存,可以减少甚至不需要再次对服务器的请求就可以显示数据。 
    
    本文将介绍如果通过HTTP协议中的header来控制浏览器的缓存行为,建议大家在看的时候写代码试验下,这样对这些header的理解会更深一点。 
    
    HTTP协议定义了四个可以用来控制浏览器缓存的HTTP头,它们是: 
    
    Last-Modified 
    Expires 
    Pragma: no-cache 
    Cache-Control 
    
    下面分别介绍HTTP/1.0和HTTP/1.1协议下的缓存解决方法。 
    
    HTTP/1.0 
    
    在HTTP/1.0协议中,Last-Modified是控制缓存的一个非常重要的HTTP头。如果需要控制浏览器的缓存,服务器首先必须发送一 个以UTC时间为值的Last-Modifeid头,当第二次访问这个页面时,浏览器会发送一个If-Modified-Since头给服务器,让服务器 判断是否有必要更新内容,这个If-Modified-Since头的值就是上次访问页面时,浏览器发送的Last-Modifeid头的值。 
    
    Expires是HTTP/1.0中另外一个很重要的HTTP头,它表示缓存的存在时间,告诉客户端浏览器在这个时间之前不对服务器发送请求,而直接使用浏览器的缓存。 
    
    在HTTP/1.0中,可以使用Pragma: no-cache头来告诉浏览器不要缓存内容,它相当于HTTP/1.1中的Cache-Control:no-cache。 
    
    如果要使用HTTP/1.0协议来告诉客户端(包括任何中介代理)是否要缓存数据,可以使用以下代码,如果设置liftTime参数则告诉客户端数据缓存的生命期为lifeTime的值: 
    
    Php代码
    function http_10_cache_headers($lifeTime = null){  
        $gmtime = time();  
        if ($lifeTime){  
            $gmtime += $lifeTime;  
        }else {  
            header("Pragma: no-cache");  
        }  
        $gmtime = gmdate('D, d M Y H:i:s',$gmtime).' GMT';  
        header("Last-Modified: $gmtime");  
        header("Expires: $gmtime");  
    }  
    function http_10_cache_headers($lifeTime = null){ $gmtime = time(); if ($lifeTime){ $gmtime += $lifeTime; }else { header("Pragma: no-cache"); } $gmtime = gmdate('D, d M Y H:i:s',$gmtime).' GMT'; header("Last-Modified: $gmtime"); header("Expires: $gmtime"); }
    
    HTTP/1.0协议的这种实现方式的缺点是,服务器和客户端的时间有可能是不同步的,这样会造成缓存的实现达不到预期效果。HTTP/1.1协议用Cache-Control头解决了这个问题。 
    
    HTTP/1.1 
    
    Cache-Control响应头的语法为: 
    Cache-Control = “Cache-Control” “:”; #缓存响应指令 
    
    缓存响应指令为一下几个中的任意一个: 
    
    1. public 
    2. private 
    3. no-cache 
    4. no-store 
    5. no-transform 
    6. must-revalidate 
    7. proxy-revalidate 
    8. max-age=时间 
    9. s-maxage=时间 
    
    详细介绍一下这几个指令的具体含义: 
    
    1. public 指示响应数据可以被任何客户端缓存 
    2. private 指示响应数据可以被非共享缓存所缓存。这表明响应的数据可以被发送请求的浏览器缓存,而不能被中介所缓存 
    3. no-cache 指示响应数据不能被任何接受响应的客户端所缓存 
    4. no-store 指示所传送的响应数据除了不能被缓存,也不能存入磁盘。一般用于敏感数据,以免数据被复制。 
    5. must-revalidate 指示所有的缓存都必须重新验证,在这个过程中,浏览器会发送一个If-Modified-Since头。如果服务器程序验证得出当前的响应数据为最新的数 据,那么服务器应当返回一个304 Not Modified响应给客户端,否则响应数据将再次被发送到客户端。 
    6. proxy-revalidate 与must-revalidate相似,不同的是用来指示共享缓存。 
    7. max-age 数据经过max-age设置的秒数后就会失效,相当于HTTP/1.0中的Expires头。如果在一次响应中同时设置了max-age和 Expires,那么max-age将具有较高的优先级。 
    8. s-maxage 与max-age相似,不同的是用来指示共享缓存。 
    
    了解这些指令后就可以根据不同的需求来发送不同的HTTP头。
    有关客户端浏览器缓存的Http头介绍
    做网站开发离不开缓存,缓存分好多种:服务器缓存,第三方缓存,浏览器缓存等。其中浏览器缓存是代价最小的,因为浏览器缓存依赖的是客户端,而几乎不耗费服务器端的资源。
    
    让浏览器做缓存需要给浏览器发送指定的Http头,告诉浏览器缓存多长时间,或者坚决不要缓存。作为.net的程序员,其实我们一直都在用这种方法,在OutputCache指令中指定缓存的Location为Client时,其实就是给浏览器发送了一个Http头,告诉浏览器这个Url要缓存多长时间,最后修改的时间。
    
    微软在OutputCacheModule中对这些缓存用到的Http头给我们进行了很好的封装,但是了解这些Http头可以更灵活的使用它们。
    
    和客户端缓存相关的Http头有以下几个,分别是:
    1. Expires:+过期时间
    表示在指定时间后浏览器缓存失效,需要注意的是这儿的过期时间必须是HTTP格式的日期时间,其他的都会被解析成当前时间“之前”,缓存会马上过期,HTTP的日期时间必须是格林威治时间(GMT),而不是本地时间。举例: 
    Expires: Fri, 30 Oct 2009 14:19:41
    
    使用Expires过期必须要求服务器的时间是正确的,否则发送的http头就会出问题,在windows服务下可以设置时间服务器来同步时间
    2. Cache-control: 
    Cache-control直译成中文就是缓存控制,它的作用就是缓存控制,这个http头的值有几种。
    1) max-age=[秒] — 执行缓存被认为是最新的最长时间。类似于过期时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过期时间,[秒]是一个数字,单位是秒:从请求时间开始到过期时间之间的秒数。 
    2) s-maxage=[秒] — 类似于max-age属性,除了他应用于共享(如:代理服务器)缓存 
    3) public — 标记认证内容也可以被缓存,一般来说: 经过HTTP认证才能访问的内容,输出是自动不可以缓存的; 
    4) no-cache — 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处); 
    5) no-store — 强制缓存在任何情况下都不要保留任何副本 
    6) must-revalidate — 告诉缓存必须遵循所有你给予副本的新鲜度的,HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,你高速缓存,你希望严格的遵循你的规则。 
    7) proxy-revalidate — 和 must-revalidate类似,除了他只对缓存代理服务器起作用 
    举例:
    Cache-Control: max-age=3600, must-revalidate
    
    很显然Cache-control可以提供比Expires更灵活的缓存控制,而且它不需要依赖于服务器时间。
    在Asp.Net中微软把对Cache-control属性的设置封装到了HttpCachePolicy类中,我们可以通过Response.Cache来调用以下方法来做到对Cache-Control Http头值的控制:
    Response.CacheControl;
    Response.Cache.SetNoStore
    Response.Cache.SetMaxAge
    Response.Cache.SetProxyMaxAge
    Response.Cache.SetRevalidation
                
    3. Last-Modified/If-Modified-Since 
    这两个Http头是一对,前者表示某个地址的最近更新时间,是服务器端响应给客户端的;而后者是客户端浏览器发送给服务器的,告诉web服务器客户端有一个最后更改时间为什么时间的缓存,服务器端接收到If-Modified-Since头后则判断客户端缓存的这份url地址的缓存是否是最新的,如果是最新的则服务器端直接给客户端返回HttpStatus 304,意思是说这个内容在你上次请求之后没有变化过,你直接用缓存就可以了;如果服务器发现url的最后更新时间比If-Modified-Since的值要新,则会输出新的内容。
    
    同样微软也为我们做了服务器端设置的封装,我们可以这样调用
    Response.Cache.SetLastModified(DateTime)
    Response.Cache.SetLastModifiedFromFileDependencies()
    
    如果有更复杂的需求就需要自己处理了。
    
    4. ETag/If-None-Match
    ETag和Last-Modified类似,不过他发送的是一个字符串来标示url的版本,如果url变了则此标示也跟着变化,在浏览器发送If-None-Match时告诉浏览器内容已经变了,或者没变可以使用缓存。
    
    Iis会自动给静态文件加上Etag,在文件发生改变时重新生成一个Etag,这样对于一个网站中的n多个静态文件如:样式表,小图片等,客户端只下载一次就够了,可以减轻负载。
    
    在Asp.Net中我们可以用以下两个方法来设置
    Response.Cache.SetETag(string)
    Response.Cache.SetETagFromFileDependencies()
    
    尽管微软为我们做了很多封装,但是我们还是需要详细的了解之后才可以用好这几个Http头。

    转自:http://hi.baidu.com/heelenyc/item/3e96013d89f98d09ceb9fee6

         http://www.cnblogs.com/yukaizhao/archive/2009/07/10/http_header_cache.html

  • 相关阅读:
    Java三年经验
    系统集成项目管理 - 笔记
    ZK
    older versions of the JRE and JDK
    [提高组集训2021] 古老的序列问题
    CF1556G Gates to Another World
    Codeforces Round #743 (Div. 1)
    [提高组集训2021] 蚂蚁
    [LOJ 6669] Nauuo and Binary Tree
    [ABC219H] Candles
  • 原文地址:https://www.cnblogs.com/blogsme/p/3393039.html
Copyright © 2011-2022 走看看