我们知道,对于WEB页面中的JS和CCS,并不会每次都请求完整的内容,有时候会直接利用本地的缓存;而对页面本身,却往往会去加载完整内容,对于服务器来说可能每次也要生成完整的内容,并送到客户端;同样的,对于一些http接口,每次调用也会去重新生成数据,浏览器也会重新加载完整的数据;
但有这样一些页面,虽然是动态的但变动频率较小,且对于同一用户重复调用可能很多(比如说个人管理后台或者新闻首页面),我们希望像js或者ccs那样在客户端缓存起来.并且,在我们希望的时候,可以更新客户端备份的那个页面,或者接口数据.是否可以做到呢;
事实上,浏览器可以缓存js,就一定能缓存我们的动态页面;
先研究下js是如何缓存起来的:
用firebug看一下js的加载:
先强刷(ctrl+F5)一下 http://ilab.iteye.com/ 页面,观看js的加载如图
状态为200 , 查一下200的含意 :
请求成功(其后是对GET和POST请求的应答文档。)
这是对js文件的完整加载;
再直接F5刷新下 http://ilab.iteye.com/ ,观看js的加载如图
状态为304,再查一下304的含意:
未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
此时其实并没有从服务端加载完整文件而是去读的本地缓存;
从304的描述来看,我们知道,请求依然发出,并由服务端告知浏览器,掉用缓存;
我们可以总结出两点:
1.
由于服务端只是返回简单的头信息,并没有生成完整页面,所以虽然请求依然发出,对于浏览器和服务器来说都更快更轻松了;
2.
我们可以控制浏览器去更新缓存;)
具此,我们可以得出结论,对于某此动态页面来说,完全可以充分利用浏览器缓存来降低服务器压力,提升客户端速度;
----------------------------------分隔线 ----------------------------------------
现在我们来看下要怎么做;
由于对文档的描述在http头信息中,并且依据304的描述,我们知道,这个属性和 Modified Time有关,我们比对下普通的页面和js的页面的respose的头信息的不同:
我们发现,多了个Last-Modified的属性;
再比对请求,
发现,多了If-Modified-Since;
武断的推测一下(或者认真的读下http协议的文档):我们可以这样认为:
1.第一次请求成功返回202;
2.假如返回头信息有Last-Modified属性 则存入浏览器缓存;
3.再次请求,假如请求的为缓存页面,则头信息中加入 If-Modified-Since;
4.服务端通过If-Modified-Since(即上次响应中Last-Modified的值)来判断是否需要更新,否的话返回304;
5.假如返回304,则浏览器则读缓存;
按照这个原理我们通过 HttpServletResponse, HttpServletRequest来偿试实现下:
对任意一个页面先来句
Java代码
- getResponse().addHeader("Last-Modified", "hello kitty");
然后再次请求该页面时,我们就可以发现请求中就有了 If-Modified-Since 属性
Java代码
- getRequest().getHeader("if-modified-since");
通过这句代码,拿到具体值;
假如判断为不用更新则直接返回304
Java代码
- getResponse().setStatus(HttpServletResponse.SC_NOT_MODIFIED);
并且立即结束返回,不用继续执行;
对于取到的if-modified-since,即是上次存入的Last-Modified,里面的值到是可以很随意,你除了放时间,也可以放memberId;
--------------------------------分隔线 ----------------------------------
实现问题也解决了;
最后一个问题,是怎么保证接口,或者页面的动态性;也就是说怎么通过Last-Modified或者if-modified-since来判断页面不需要更新;
考虑最简单的情况,这个接口或者页面仅提供和用户相关的不同信息,并且该信息一但建立则不会改变;
那对于此接口,假如参数中包含memberId属性,则一但具有if-modified-since值,则永远返回304;因为对于不同url,浏览器均会进行缓存;
假如memberId属性在cookie中,url一致,那么,在Last-Modified中存入memberId,判断时于cookie或者session中url比对,相同则认为是正确的缓存返回304;
现在,新的问题来了,用户的相关信息更新了;
假如这个更新频率不是那么频繁,那么想办法做个更新机制还是合理的;你需要一个地方在服务端记录用户接口信息的版本号了,从if-modified-since中取得上次的版本号,然后进行比对,如果相同,则返回304;
在某些情况下,获取更新记录信息要比计算合成完整信息并利用带宽将数据传给客户端代价小得多,此时你可以试下WEB服务动态接口的静态缓存;
【编辑推荐】