http相应通过三个MIME指定缓存的策略:
eg:
HTTP:/1.1 200 OK
Date:Sun,21 Apr 2015 15:15:15 GMT
Server:Apache
Connection:close
Content-Type:text/*;charset=gbk
Cache-control:max-age=604800
Expires:Sun,28 Apr 2015 15:15:15 GMT
Last-modified:Sat,20 Apr 2014 15:15:15 GMT
Etag:"23456asdfg3456dfg"
Etag
Expires
Cache-control
Last-modified
1、Etag是一个ASCII文本串,客户端通过比较“首部”包含的Etag信息来判断缓存是否失效;
2、Expires指示资源缓存到期的时间;eg:Expires: Thu, 01 Dec 1994 16:00:00 GMT (必须是GMT格式)
3、Cache-control提供了更“细粒度”的缓存策略,且当Expires和Cache-control同时出现时,后者将覆盖前者,Cache-control的属性有:
a、no-cache 这个策略的作用和名字不太一致。缓存项仍然可以缓存,不过客户端在每次访问是要用Etag或Last-modified首部重新验证响应状态;
b、no-store 不管怎样都不使用缓存;
c、max-age 指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
d、public 可以缓存一个“经过认证”的响应,不设置时,已经认证的响应不能缓存;
f、private 仅单个用户缓存可以保存响应,而共享缓存不应保存;
g、s-maxage 缓存项在共享缓存中的过期秒数,私有缓存可以将缓存项保存更长时间;
4、指示资源最后一次修改的日期,客户端可以使用HEAD请求来检查这个日期,判断是否需要用GET重新获取资源;
下面用java实现cache-control的解析与查询:
定义CacheControl类,代码如下:
package com.z;
import java.util.Date;
import java.util.Locale;
public class CacheControl {
private boolean noCache = false;
private boolean noStore = false;
private Date maxAge;
private boolean isPublic = false;
private boolean isPrivate = false;
private Date sMaxAge;
public boolean noCache(){
return noCache;
}
public boolean noStore(){
return noStore;
}
public Date maxAge(){
return maxAge;
}
public boolean publicCache(){
return isPublic;
}
public boolean privateCache(){
return isPrivate;
}
public Date sMaxAge(){
return sMaxAge;
}
public CacheControl(String cacheControl){
if(cacheControl == null || !cacheControl.contains(":"))
return;
String value = cacheControl.split(":")[1].trim();
String[] components = value.split(",");
Date now = new Date();
for(String component : components){
try{
component = component.trim().toLowerCase(Locale.US);
if(component.startsWith("no-cache")){
this.noCache = true;
}else if(component.startsWith("no-store")){
this.noStore = true;
}else if(component.startsWith("max-age")){
int secondsInTheFuture = Integer.parseInt(component.substring(8));
this.maxAge = new Date(now.getTime() + 1000 * secondsInTheFuture);
}else if(component.startsWith("public")){
this.isPublic = true;
}else if(component.startsWith("private")){
this.isPrivate = true;
}else if(component.startsWith("s-maxage")){
int secondsInTheFuture = Integer.parseInt(component.substring(8));
this.sMaxAge = new Date(now.getTime() + 1000 * secondsInTheFuture);
}
}catch(RuntimeException ex){
continue;
}
}
}
}