`
ajax
  • 浏览: 251824 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Restlet实战(二十五)缓存 (Cache)

    博客分类:
  • REST
阅读更多

说明:以下部分文字说明摘自<<Restful Web Service>>.

条件GET机制令客户端可以在表示没有发生变化时,只使用很少的带宽。而缓存机
制使得客户端可以根本不必要发送第二次GET请求。

其基本原理是:

客户端在做HTTP GET或HEAD请求时,可以把服务器返回的HTTP响应报头缓存起来;这样,当客户端再次发
出相同的GET或HEAD请求时,可以直接采用缓存中的文档,而不必实际发出请求。缓存机制是透明的,用
户要客户端发出请求,但是客户端并没有实际发出HTTP请求,并接收来自服务器的响应,而是把缓存中的
响应返回给用户,仿佛刚从服务器得到的一样。可以从服务器角度关注三个问题:服务器如何通知客户端
可以缓存;服务器如何通知客户端不要缓存;何时客户端可以在服务器不知情的情况下进行缓存。 

 

了解了原理后,我们来看看如何使用Restlet实现缓存:

 

1. 服务器端通知客户端可以缓存

 

客户端第一次请求一个资源时,这个时候没有缓存,因为这个需要等待服务器通知后,客户端才可以缓存。服务器端我们设置两个Header: Expires和cache-control.代码如下:

 

@Override 
public Representation represent(Variant variant) { 
	String userMsg = customerDAO.getCustomerById(customerId); 
	Representation representation = new StringRepresentation(userMsg, MediaType.TEXT_PLAIN); 
	
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
	Date expirationDate = null; 
	try { 
		expirationDate = format.parse("2009-07-29 00:00:00"); 
	} catch (ParseException e) { 
		e.printStackTrace(); 
	} 
	representation.setExpirationDate(expirationDate); 
	
	Form resHeaders = (Form)getResponse().getAttributes().get("org.restlet.http.headers"); 
	if (resHeaders == null) { 
		resHeaders = new Form(); 
	} 
	resHeaders.add("Cache-Control", "max-age=3600"); 
	getResponse().getAttributes().put("org.restlet.http.headers", resHeaders); 
	
	return representation; 
}

 

在这段代码里,我们设置了Expires和Cache-Control,但是你会发现两种header的设置方式不一样,对于Expires,Restlet直接提供了设置方法,而对于Cache-Control,我们不得不通过设置Attribute的方式来实现。这是因为当前版本,也就是1.1的版本,restlet还没有提供这样的方法,在restlet2.0M5,甚至正式版将会在Representation里直接提供这些设置标准Header的方法。

 

感兴趣的话,可以查看HttpConverter类来查看Restlet1.1的版本已经为哪些Header提供了直接的方法支持,而哪些在以后新的版本中提供。

 

另外一个需要说明的一点是,Cache-Control的值,我们设置了max-age=3600,注意,如果设置这个值,那么它会覆盖Expires。

 

万事具备,让我们测试一下,打开浏览器输入URL(我本机环境是:http://localhost:8080/restlet/resources/customers/1),并且为了方便查看结果,你可以在上面的方法上加入断点,当第一次请求的时候,服务器端会收到请求,当后面再继续用同样的URL做请求时,你会发现服务器端代码没有执行,实际上就是浏览器已经把返回的header和表示做了缓存。当第二次以及以后再次请求,都是从缓存中取回表示(Representation)。

 

让我们采用Httpclient来重新测试一下,

 

HttpClient client = new HttpClient(); 
HttpMethod get = new GetMethod("http://localhost:8080/restlet/resources/customers/1"); 
boolean isCached = false; 
boolean hasMaxAge = false; 
String expirationDate = null; 

client.executeMethod(get); 
Header[] headers = get.getResponseHeaders(); 

for(int i = 0; i < headers.length; i++){ 
	Header header = headers[i]; 
	if(header.getName().equals("Cache-Control")){ 
		isCached = true; 
		if(header.getValue().startsWith("max-age")){ 
			hasMaxAge = true; 
		} 
	}else if(header.getName().equals("Expires")){ 
		expirationDate = header.getValue(); 
	} 
} 

if(isCached){ 
	if(hasMaxAge){ 
		//Cache the representation and save max age 
	}else if(expirationDate != null && !expirationDate.equals("")){ 
		//Cache the representation and save expiration date 
	} 
} 

 

之所以贴出这段代码,主要想说明,如果使用浏览器的话,判断响应是否包含cache的header,并根据这个header来判断是否cache表示,这个过程被浏览器自动的处理了,而如果是人为的客户端程序,这些判断已经缓存的过程需要我们自己来处理。当然了,是放到缓存里,还是文件或者数据库,这要根据你项目的架构来定。

 

2.服务器通知客户端不要缓存

 

有了上面的处理,这个就很简单了,指定Cache-Control的值为:no-cache,以禁止客户端进行缓存,也可以把Cache-Control的值设置成private,表示该响应能够被客户端缓存,不能被代理缓存。当然了Cache-Control的值不止我提到的这几个,更多的你可以查看HTTP规范。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics