您的位置:首页 > 编程语言 > ASP

Web开发中的缓存技术之三:通过ETag实现缓存处理(ASP.NET MVC版)

2010-04-04 21:46 751 查看
IIS已经为我们提供了其内置的缓存功能。但显得比较死板,对于更高的要求,IIS的缓存功能显然就有些不够灵活了。

在mvc风格的开发中我们可以通过Filter来定制缓存方式。

本篇介绍借助ETag响应头实现缓存,没有完美的缓存方案,这种方式能够准确判断客户浏览器缓存是否需要更新,但不会避免服务器再次生成页面的过程,它的主要用意在于避免不必要的数据传输,减少流量缓解带宽压力。

何为ETag,以及Is-Non-Match

您可以把ETag理解为HTTP通信中存在的一个附加信息,服务器产生ETag,客户机浏览器下一次再访问此页面时会在将此值放在Request Headers中的Is-Non-Match里。ETag、Is-Non-Match的一个经典用途就是用于缓存实现。下面会为您详细说明如何通过ETag在ASP.NET MVC中实现缓存处理。

关于ETag,您可以去看看W3C的说明:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

基本原理

服务器将数据传给客户浏览器前会对页面数据进行哈希计算,并将哈希值转为Base64编码的ASCII字符以存放在Response响应头的ETag信息中。客户机浏览器在接收到来自服务器的信息后会将ETag值缓存到本地,下一次再访问这个页面时就会将此ETag值放在Request头的Is-Non-Match中,服务器仍然会生成页面,但要与此ETag值进行比较,如果相同就说明客户机浏览器中缓存的页面与即将传输的内容一致,进而就不会将重复的页面传输过去而是将状态置为304,这样就减少了不必要的带宽占用。

如何实现

我们要做的是让服务器去接受响应并生成数据,但是在将其写入到流中之前要对即将写入的内容进行检查,看其经过Hash计算的值是否与Is-Non-Match中的值相同,如果相同就将HTTP状态置为304,否则更新ETag并将数据写入到流中。为实现这个目的,我定义了一个包装流,将HttpResponseBase.Filter替换为包装流来方便我们在数据送到客户机之前获得数据。

(说明:asp.net mvc的ActionFilter与java里的那个Filter不太一样,一开始我以为执行到OnResultExecuted时写在response里的内容就已经存在了,后来才发现向Stream里写入数据的过程要在OnResultExecuted之后,于是我只好变相在自定义的ResponseWrapper这个Stream包装流里去处理response。)

效果展示

应用示例

[HandleError]
public class HomeController : Controller
{
[ContentCacheFilter]
//[LazyCacheFilter]
public ActionResult Index()
{
//ViewData["Message"] = DateTime.Now.ToString();
ViewData["Message"] = "this is from asp.net mvc development server";
return View();
}

public ActionResult About()
{
return View();
}
}

ResponseWrapper的实现可能略显不妥,大家有更好的方案希望多多分享哈^^

源码放在skydriver上了,下载页面链接(这是个页面链接迅雷会误认为是文件,刚发现skydriver给的直接下载链接都是带时间戳的,过了一天就不能用了。。。):

http://cid-ebf46737d420f3e0.skydrive.live.com/self.aspx/By%20Sopaco/Sopaco.Lib.Web.Mvc.Filters/Filters.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐