一个具有缓存数据功能的HttpWebRequest工具类
来源:互联网 发布:java分布式是什么意思 编辑:程序博客网 时间:2024/06/03 15:56
背景:一个公共站点中的数据,供其它子站点共享,为了提高性能,简单实现了Http 1.1的缓存功能
特点:可以缓存Html数据到内存中;缓存具有过期时间;缓存过期后,通过再确认的方式来决定是否更新缓存;浏览器刷新后,无论缓存是否过期都会强制再验证;
未实现的包括:不能通过no-store来强制清空缓存,缓存再确认时没有验证Etag
/// <summary> /// 启用缓存的HttpRequest /// </summary> public static class CacheHttpRequest { private static Dictionary<String,HtmlLocalCache> _caches = new Dictionary<string,HtmlLocalCache>(); private static object AddCacheLock = new Object(); public static String GetHtml(String url) { HtmlLocalCache cache; //如果有缓存,且缓存尚未过期,或不需要重新验证,则直接返回内容 if(_caches.TryGetValue(url,out cache)) { if(!cache.NeedRevalidate()) { return cache.Html; } } var webRequest = (HttpWebRequest)WebRequest.Create(url); //如果有缓存,且需要重新验证,则设置它的IMS信息,为了简便,这里没有验证ETag if(cache != null) { webRequest.IfModifiedSince = cache.LastModified; } HttpWebResponse response = null; Stream stream = null; try { response = webRequest.GetHttpResponse(); //如果服务器资源没有修改,则修改缓存信息后,返回内容 if (cache != null && response.StatusCode == HttpStatusCode.NotModified) { cache.UpdateCacheProperty(response); return cache.Html; } //服务器资源已经修改,重新获取内容,并放入缓存 if (response.StatusCode == HttpStatusCode.OK) { stream = response.GetResponseStream(); TextReader reader = new StreamReader(stream); cache = new HtmlLocalCache(); cache.SetCacheProperty(response); cache.Html = reader.ReadToEnd(); AddHtmlToCache(url, cache); return cache.Html; } return ""; } finally { if(response != null) response.Close(); if(stream != null) stream.Dispose(); } } private static void AddHtmlToCache(string url, HtmlLocalCache cache) { lock (AddCacheLock) { if (!_caches.ContainsKey(url)) { _caches.Add(url, cache); } } } /// <summary> /// 缓存数据 /// </summary> private class HtmlLocalCache { public String Html; public DateTime LastModified; public DateTime? ExpiredTime; public DateTime HttpDate; private Object _updateLock = new Object(); public Boolean NeedRevalidate() { if (ExpiredTime == null) return true; if (FromRefresh()) return true; return DateTime.Now > ExpiredTime; } /// <summary> /// 看是否是页面刷新 /// </summary> /// <returns></returns> private static bool FromRefresh() { string requestCacheControl = HttpContext.Current.Request.Headers["Cache-Control"]; String pragma = HttpContext.Current.Request.Headers["Pragma"]; Boolean isRefresh = (pragma != null && pragma.Equals("no-cache", StringComparison.OrdinalIgnoreCase) || requestCacheControl != null && requestCacheControl.Equals("no-cache", StringComparison.OrdinalIgnoreCase)); if (isRefresh) return true; return false; } private void SetCacheControl(string cacheControl) { if (String.IsNullOrEmpty(cacheControl)) return; if(cacheControl.Contains("max-age")) { Double maxAge = Double.Parse(cacheControl.Substring(cacheControl.IndexOf('=')+1)); ExpiredTime = HttpDate.AddSeconds(maxAge); } } public void SetCacheProperty(HttpWebResponse response) { LastModified = response.LastModified; HttpDate = Convert.ToDateTime(response.Headers["Date"]); //使用cache-control来控制缓存过期时间,不使用expires SetCacheControl(response.Headers["Cache-Control"]); } public void UpdateCacheProperty(HttpWebResponse response) { lock (_updateLock) { SetCacheProperty(response); } } } }
- 一个具有缓存数据功能的HttpWebRequest工具类
- 具有缓存功能的ServiceLocator
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- 实现一个具有百度文库文档转换功能的工具类
- C++练习:一个具有深拷贝功能的字符串类
- 设计:设计一个分数类,具有一下的功能
- 一个具有对象计数功能的基类
- 缓存功能工具类
- Unity内使用HttpWebRequest下载数据,缓存问题的解决
- 实现一个具有GetMin功能的栈
- 设计一个具有GetMin功能的栈
- 设计一个具有getMin()功能的栈
- linux虚拟机鼠标切换和屏幕大小问题
- 面试题
- jquery $.ajax SyntaxError: invalid label /Uncaught SyntaxError: Unexpected token :
- SQL语句
- BCP学习(5):BCP常见问题集
- 一个具有缓存数据功能的HttpWebRequest工具类
- CStatic控件重载,有所补充
- js中cookie的使用详细分析
- 一个用python写的websocket服务端
- 在html页面插入flv播放器。ie火狐均可用
- Emacs编辑器——王垠
- 单链表详解(创建,插入,删除,打印)
- android系统root与应用程序获取root权限原理总结
- Linux--I2C驱动分析