在Asp.Net 4.0 的web.config文件中添加了关于缓存的配置节,如下所示:
| 02 |
<compilation debug="true" targetFramework="4.0" /> |
| 04 |
<outputCache defaultProvider="SmartOutputCache"> |
| 06 |
<add name="SmartOutputCache" type="OutputCacheTest.Caching.SmartOutputCacheProvider" |
| 07 |
memoryCacheLimit="00:30:00" |
我们可以在Web.config中配置自定义的OutputCacheProvider,并将自定义Provider指定为默认的Provider。
1.自定义OutputCacheProvider需要实现System.Web.Cacheing. OutputCacheProvider抽象类,网上有很多例子都用文件缓存做例子。这个例子太俗了,我写了一个新的例子,在设置的缓存时间小于指定阀值时,缓存到HttpRuntime.Cache中,否则缓存到文件中,如下代码:
| 002 |
using System.Collections.Generic; |
| 005 |
using System.Web.Caching; |
| 006 |
using System.Xml.Serialization; |
| 008 |
using System.Runtime.Serialization.Formatters.Binary; |
| 010 |
namespace OutputCacheTest.Caching |
| 013 |
/// OutputCache精灵,如果缓存时间小于设置时间时则缓存到内存,否则缓存到文件 |
| 015 |
public class SmartOutputCacheProvider : OutputCacheProvider |
| 017 |
private const string KEY_PREFIX = "__outputCache_"; |
| 020 |
/// 初始化SmartOutputCacheProvider,读取配置文件中配置的MemoryCacheLimit和FileCacheRoot的值 |
| 024 |
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) |
| 026 |
string memoryLimit = config["memoryCacheLimit"]; |
| 027 |
if (memoryLimit == null) |
| 029 |
MemoryCacheLimit = new TimeSpan(0, 30, 0); |
| 033 |
MemoryCacheLimit = TimeSpan.Parse(memoryLimit); |
| 036 |
string fileCacheRoot = config["fileCachRoot"]; |
| 037 |
if (string.IsNullOrEmpty(fileCacheRoot)) |
| 039 |
fileCacheRoot = AppDomain.CurrentDomain.BaseDirectory + "cache\\"; |
| 041 |
this.FileCacheRoot = fileCacheRoot; |
| 042 |
base.Initialize(name, config); |
| 048 |
/// 缓存的键,key的值是有asp.net内部生成的 |
| 052 |
public override object Add(string key, object entry, DateTime utcExpiry) |
| 054 |
Set(key, entry, utcExpiry); |
| 059 |
/// 处理缓存键值,防止在文件缓存时出现文件路径不允许的字符 |
| 063 |
private string ProcessKey(string key) |
| 065 |
return KEY_PREFIX + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5"); |
| 073 |
private string GetFilePath(string processedKey) |
| 075 |
return Path.Combine(FileCacheRoot, processedKey + ".data"); |
| 079 |
/// 获得缓存值,如果在HttpRuntime.Cache中有则直接读取内存中的值,否则从文件读取 |
| 083 |
public override object Get(string key) |
| 085 |
string processedKey = ProcessKey(key); |
| 087 |
CacheDataWithExpiryTimeUtc result = HttpRuntime.Cache[processedKey] as CacheDataWithExpiryTimeUtc; |
| 090 |
string path = GetFilePath(processedKey); |
| 091 |
if (!File.Exists(path)) |
| 094 |
using (FileStream file = File.OpenRead(path)) |
| 096 |
var formatter = new BinaryFormatter(); |
| 097 |
result = (CacheDataWithExpiryTimeUtc)formatter.Deserialize(file); |
| 101 |
if (result == null || result.ExpiryTimeUtc <= DateTime.UtcNow) |
| 113 |
public override void Remove(string key) |
| 115 |
string processedKey = ProcessKey(key); |
| 116 |
HttpRuntime.Cache.Remove(processedKey); |
| 117 |
string path = GetFilePath(processedKey); |
| 118 |
if (!File.Exists(path)) |
| 128 |
public override void Set(string key, object entry, DateTime utcExpiry) |
| 130 |
TimeSpan ts = utcExpiry - DateTime.UtcNow; |
| 131 |
string processedKey = ProcessKey(key); |
| 133 |
CacheDataWithExpiryTimeUtc cacheItem = new CacheDataWithExpiryTimeUtc |
| 136 |
ExpiryTimeUtc = utcExpiry |
| 139 |
if (ts <= MemoryCacheLimit) |
| 141 |
HttpRuntime.Cache.Insert(processedKey, cacheItem, null, utcExpiry.ToLocalTime(), TimeSpan.Zero); |
| 145 |
string cacheFilePath = GetFilePath(processedKey); |
| 147 |
using (var fs = new FileStream(cacheFilePath,FileMode.OpenOrCreate,FileAccess.ReadWrite)) |
| 149 |
var formatter = new BinaryFormatter(); |
| 150 |
formatter.Serialize(fs, cacheItem); |
| 156 |
/// 如果缓存设定的时间超过此值则缓存到文件中,否则在HttpRuntime.Cache中做缓存 |
| 158 |
[XmlAttribute("memoryCacheLimit")] |
| 159 |
public TimeSpan MemoryCacheLimit { get; set; } |
| 163 |
/// 文件缓存的根目录,可以指定任何可访问目录 |
| 165 |
[XmlAttribute("fileCacheRoot")] |
| 166 |
public string FileCacheRoot { get; set; } |
| 173 |
internal class CacheDataWithExpiryTimeUtc |
| 175 |
public object Data { get; set; } |
| 177 |
public DateTime ExpiryTimeUtc { get; set; } |
2.如何使用自定义的OutputCacheProvider
1)在配置文件中做配置,将自定义的实现作为默认输出缓存支持,请看文章开始的配置
2)在UserControl中指定使用Provider的名字,改名字在web.config中定义,例如
| 1 |
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="IamUserControl.ascx.cs" Inherits="OutputCacheTest.IamUserControl" %> |
| 2 |
<%@ OutputCache Duration="3000" ProviderName="AspNetInternalProvider" VaryByParam="None" %> |
需要注意的是,只能在UserControl中指定Provider的名字,在Page的生明中是不允许的,在Page中默认情况会使用web.config中配置的defaultProvider,但是我们可以通过3)中介绍的方法给不同的页面使用不同的OutputCacheProvider实现。
3)在Global.asax文件中重写GetOutputCacheProviderName(HttpContext context)方法,根据context返回不同的实现名字,如下例子
| 1 |
public override string GetOutputCacheProviderName(HttpContext context) |
| 3 |
if (context.Request.Path.StartsWith("/default.aspx",StringComparison.CurrentCultureIgnoreCase)) |
| 5 |
return "AspNetInternalProvider"; |
| 8 |
return base.GetOutputCacheProviderName(context); |
总结:
可扩展的OutputCache为我们提供了无限的可能,我们可以根据需要扩展OutputCache,例如把OutputCache存储到Memcached server或者其他键值对数据存储中,从而使程序的性能达到最优的情况。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-662874/
,如需转载,请注明出处,否则将追究法律责任。