前言
眾所周知,各個大型網站為了提升網站訪問性能或多或少的都有用一些緩存來提升應用性能,其中最為常用的可能就是生成HTMl頁面了,這種方法從某種意義上來說,可以納入文件緩存的范圍里。不過這種做法有一些弊端(對我來說),沒有一套完整的HTML文件管理機制,導致大量的HTML代碼的管理是件非常頭痛的事情。
我們今天就來講講另外一種我們很常用並且很簡單的做法,那就是 ASP.NET 的輸出緩存 OutputCache
OutputCache
對於各位做WEB開發的 Neter 來說,想必OutputCache一定不會陌生了,在 WebForm 中,我們在aspx頁面頂端包含 OutputCache 設置 : <%@OutputCache VaryByParam="none" Duration="10" %>,在 ASP.NET MVC 中,我們在 Controller/ Action 上添加該屬性來緩存數據來提升程序性能:
public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); } [OutputCache(Duration = 10, VaryByParam = "none")] public ActionResult About() { return View(); } }
OutputCache 的缺點
那么 OutputCache 到底有什么缺點呢?我們都知道 OutputCache 輸出緩存是存儲在內存中的,也就是說這種做法就已經限定只能用在小型網站中,因為如果我們的網站中包含大量的基於內存的緩存,恐怕會非常消耗主機內存的。
OutputCache 完善
鑒於OutputCache 基於內存保存這一問題,我們對 OutputCache 來進行擴展解決這一問題,此時就要用到 .net framework 4 中的 OutputCacheProvider,借助OutputCacheProvider,我們可以有多種選擇創建自己的緩存,本節我就來擴展下 OutputCache 來創建自定義文件緩存。
借助OutputCacheProvider擴展OutputCache創建自定義文件緩存
創建類:FileCacheProvider,引入 using System.Web.Caching; 命名空間,繼承自 OutputCacheProvider 抽象類,重寫 四個方法 :
Add 方法,將指定項插入輸出緩存中。
Get 方法,返回對輸出緩存中指定項的引用。
Remove 方法,從輸出緩存中移除指定項。
Set 方法,將指定項插入輸出緩存中,如果該項已緩存,則覆蓋該項。
public class FileCacheProvider : OutputCacheProvider { public string CachePath { get; set; } private string ConvertKeyToPath(string key) { string file = key.Replace('/', '-'); file += ".txt"; return Path.Combine(CachePath, file); } public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { base.Initialize(name, config); //讀取 CachePath = HttpContext.Current.Server.MapPath(config["cachePath"]); } public override object Add(string key, object entry, DateTime utcExpiry) { object obj = Get(key); if (obj != null) { return obj; } Set(key, entry, utcExpiry); return entry; } public override object Get(string key) { string path = ConvertKeyToPath(key); if (!File.Exists(path)) { return null; } CacheItem item = null; using (FileStream file = File.OpenRead(path)) { var formatter = new BinaryFormatter(); item = (CacheItem)formatter.Deserialize(file); } if (item.ExpiryDate <= DateTime.Now.ToUniversalTime()) { //log Remove(key); return null; } return item.Item; } public override void Set(string key, object entry, DateTime utcExpiry) { CacheItem item = new CacheItem(entry, utcExpiry); string path = ConvertKeyToPath(key); using (FileStream file = File.OpenWrite(path)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(file, item); } } public override void Remove(string key) { string path = ConvertKeyToPath(key); if (File.Exists(path)) { File.Delete(path); } } } [Serializable] public class CacheItem { public DateTime ExpiryDate; public object Item; public CacheItem(object entry, DateTime utcExpiry) { Item = entry; ExpiryDate = utcExpiry; } }
實例程序中,我將緩存放在 Config 文件配置的 cachePath 目錄中,具體請看 Initialize 方法。
配置文件
需要在Web.Config 文件中配置緩存處理程序驅動
<system.web> <caching> <outputCache defaultProvider="FileCache"> <providers> <add name="FileCache" type="FileCache.Provider.FileCacheProvider" cachePath="~/Cache"/> </providers> </outputCache> </caching>
如何使用?
以上配置好之后,使用就很容易了,因為是對 Asp.NET 輸出緩存 OutputCache 進行了擴展,所以使用方式 和之前的用法一樣,我在MVC中使用如下:
namespace FileCache.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); } [OutputCache(Duration = 10, VaryByParam = "none")] public ActionResult About() { return View(); } } }
可以看到,我在 About Action 上打緩存標記 [OutputCache(Duration = 10, VaryByParam = "none")] ,設置緩存時間10分鍾,並且不根據任何參數重新緩存,運行,可以再配置好的 Cache 文件下看到緩存文件:
運行程序后,訪問 About 頁面,將會看到在Cache文件夾產生了緩存文件。
注意事項
我是在項目中提前創建好了 Cache 文件夾,當然這個文件夾名稱可以隨便取了,只需要在 Web.Config 映射正確即可,如果您運行報錯,可能是由於該文件夾不存在,或者您可以再 緩存擴代碼中判斷一下是否存在 Cache 文件夾,沒有則程序創建即可。
遺留問題
以上我們可以看到是將緩存文件保存成 txt 文本,那么我們是否可以將其保存為xml 格式文件以及哪種格式性能好呢?如果選用 xml ,可以進一步修改使用泛型類來解決 不同對象的xml序列化問題。若您有更好的建議,不妨提出。