Asp.Net 4.0 新特性之 使用自定义OutputCache Provider(转)

在Asp.Net 4.0 的web.config文件中添加了关于缓存的配置节,如下所示:

01<system.web>
02  <compilation debug="true" targetFramework="4.0" />
03  <caching>
04    <outputCache defaultProvider="SmartOutputCache">
05      <providers>
06        <add name="SmartOutputCache" type="OutputCacheTest.Caching.SmartOutputCacheProvider" 
07             memoryCacheLimit="00:30:00"
08             />
09      providers>
10    outputCache>
11  caching>
12system.web>

我们可以在Web.config中配置自定义的OutputCacheProvider,并将自定义Provider指定为默认的Provider。

1.自定义OutputCacheProvider需要实现System.Web.Cacheing. OutputCacheProvider抽象类,网上有很多例子都用文件缓存做例子。这个例子太俗了,我写了一个新的例子,在设置的缓存时间小于指定阀值时,缓存到HttpRuntime.Cache中,否则缓存到文件中,如下代码:

001using System;
002using System.Collections.Generic;
003using System.Linq;
004using System.Web;
005using System.Web.Caching;
006using System.Xml.Serialization;
007using System.IO;
008using System.Runtime.Serialization.Formatters.Binary;
009  
010namespace OutputCacheTest.Caching
011{
012    ///
013    /// OutputCache精灵,如果缓存时间小于设置时间时则缓存到内存,否则缓存到文件
014    ///
015    public class SmartOutputCacheProvider : OutputCacheProvider
016    {
017        private const string KEY_PREFIX = "__outputCache_";
018  
019        ///
020        /// 初始化SmartOutputCacheProvider,读取配置文件中配置的MemoryCacheLimit和FileCacheRoot的值
021        ///
022        /// provider名字
023        /// 配置
024        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
025        {
026            string memoryLimit = config["memoryCacheLimit"];
027            if (memoryLimit == null)
028            {
029                MemoryCacheLimit = new TimeSpan(0, 30, 0);
030            }
031            else
032            {
033                MemoryCacheLimit = TimeSpan.Parse(memoryLimit);
034            }
035  
036            string fileCacheRoot = config["fileCachRoot"];
037            if (string.IsNullOrEmpty(fileCacheRoot))
038            {
039                fileCacheRoot = AppDomain.CurrentDomain.BaseDirectory + "cache\\";
040            }
041            this.FileCacheRoot = fileCacheRoot;
042            base.Initialize(name, config);
043        }
044  
045        ///
046        /// 添加缓存
047        ///
048        /// 缓存的键,key的值是有asp.net内部生成的
049        /// 缓存的对象
050        /// 过期时间
051        /// 返回缓存值
052        public override object Add(string key, object entry, DateTime utcExpiry)
053        {
054            Set(key, entry, utcExpiry);
055            return entry;
056        }
057  
058        ///
059        /// 处理缓存键值,防止在文件缓存时出现文件路径不允许的字符
060        ///
061        /// 缓存键
062        /// 处理后的键
063        private string ProcessKey(string key)
064        {
065            return KEY_PREFIX + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5");
066        }
067  
068        ///
069        /// 返回缓存文件的物理路径
070        ///
071        /// 处理后的键
072        /// 物理路径
073        private string GetFilePath(string processedKey)
074        {
075            return Path.Combine(FileCacheRoot, processedKey + ".data");
076        }
077  
078        ///
079        /// 获得缓存值,如果在HttpRuntime.Cache中有则直接读取内存中的值,否则从文件读取
080        ///
081        /// 缓存键
082        /// 缓存值
083        public override object Get(string key)
084        {
085            string processedKey = ProcessKey(key);
086  
087            CacheDataWithExpiryTimeUtc result = HttpRuntime.Cache[processedKey] as CacheDataWithExpiryTimeUtc;
088            if (result == null)
089            {
090                string path = GetFilePath(processedKey);
091                if (!File.Exists(path))
092                    return null;
093  
094                using (FileStream file = File.OpenRead(path))
095                {
096                    var formatter = new BinaryFormatter();
097                    result = (CacheDataWithExpiryTimeUtc)formatter.Deserialize(file);
098                }
099            }
100  
101            if (result == null || result.ExpiryTimeUtc <= DateTime.UtcNow)
102            {
103                Remove(key);
104                return null;
105            }
106            return result.Data;
107        }
108  
109        ///
110        /// 根据键移除缓存
111        ///
112        /// 缓存键
113        public override void Remove(string key)
114        {
115            string processedKey = ProcessKey(key);
116            HttpRuntime.Cache.Remove(processedKey);
117            string path = GetFilePath(processedKey);
118            if (!File.Exists(path))
119                File.Delete(path);
120        }
121  
122        ///
123        /// 设置缓存
124        ///
125        /// 缓存键
126        /// 缓存内容
127        /// 过期时间
128        public override void Set(string key, object entry, DateTime utcExpiry)
129        {
130            TimeSpan ts = utcExpiry - DateTime.UtcNow;
131            string processedKey = ProcessKey(key);
132  
133            CacheDataWithExpiryTimeUtc cacheItem = new CacheDataWithExpiryTimeUtc
134            {
135                Data = entry,
136                ExpiryTimeUtc = utcExpiry
137            };
138  
139            if (ts <= MemoryCacheLimit)
140            {
141                HttpRuntime.Cache.Insert(processedKey, cacheItem, null, utcExpiry.ToLocalTime(), TimeSpan.Zero);
142            }
143            else
144            {
145                string cacheFilePath = GetFilePath(processedKey);
146                  
147                using (var fs = new FileStream(cacheFilePath,FileMode.OpenOrCreate,FileAccess.ReadWrite))
148                {
149                    var formatter = new BinaryFormatter();
150                    formatter.Serialize(fs, cacheItem);
151                }
152            }
153        }
154  
155        ///
156        /// 如果缓存设定的时间超过此值则缓存到文件中,否则在HttpRuntime.Cache中做缓存
157        ///
158        [XmlAttribute("memoryCacheLimit")]
159        public TimeSpan MemoryCacheLimit { get; set; }
160  
161  
162        ///
163        /// 文件缓存的根目录,可以指定任何可访问目录
164        ///
165        [XmlAttribute("fileCacheRoot")]
166        public string FileCacheRoot { get; set; }
167    }
168  
169    ///
170    /// 对缓存数据和缓存的过期时间的封装
171    ///
172    [Serializable]
173    internal class CacheDataWithExpiryTimeUtc
174    {
175        public object Data { get; set; }
176  
177        public DateTime ExpiryTimeUtc { get; set; }
178    }
179}

2.如何使用自定义的OutputCacheProvider

  1)在配置文件中做配置,将自定义的实现作为默认输出缓存支持,请看文章开始的配置
  2)在UserControl中指定使用Provider的名字,改名字在web.config中定义,例如

  需要注意的是,只能在UserControl中指定Provider的名字,在Page的生明中是不允许的,在Page中默认情况会使用web.config中配置的defaultProvider,但是我们可以通过3)中介绍的方法给不同的页面使用不同的OutputCacheProvider实现。

  3)在Global.asax文件中重写GetOutputCacheProviderName(HttpContext context)方法,根据context返回不同的实现名字,如下例子

1public override string GetOutputCacheProviderName(HttpContext context)
2{
3    if (context.Request.Path.StartsWith("/default.aspx",StringComparison.CurrentCultureIgnoreCase))
4    {
5        return "AspNetInternalProvider";
6    }
7              
8    return base.GetOutputCacheProviderName(context);
9}

总结:
可扩展的OutputCache为我们提供了无限的可能,我们可以根据需要扩展OutputCache,例如把OutputCache存储到Memcached server或者其他键值对数据存储中,从而使程序的性能达到最优的情况。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12639172/viewspace-662874/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12639172/viewspace-662874/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值