在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中定義,例如
需要注意的是,只能在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部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-662874/,如需轉載,請註明出處,否則將追究法律責任。