一个具有缓存数据功能的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);                }            }        }    }

原创粉丝点击