為什么要使用OutputCache
我認為OutputCache是最簡單的緩存技術了,它針對的是頁面級別的,簡單的一條指令就可以達到緩存的效果,有效的減輕服務器的壓力和減少帶寬,對於網站一些不會頻繁更新內容的頁面,我們可以使用OutputCache來提供性能。
為什么要更新OutputCache
作為網站的管理者,肯定要賦予他控制網站每一個部分的能力,假如網站要更新一個內容,而OutputCache還沒有失效,難道要重啟站點來生效嗎?這時候,一個更新OutputCache的功能就顯得很有必要了。
如何更新OutputCache
一、 webForm
首先,我們看看OutputCache的效果,在Index.aspx 頁面的上面添加這樣一條OutputCache指令,意思為頁面緩存10秒鍾,並且不針對任何的參數。
<%@ OutputCache Duration="10" VaryByParam="none"%>
然后再后台Page_Load函數里,輸出當前的時間
public partial class Index : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.Write(DateTime.Now.ToString()); } }
瀏覽器查看Index.aspx頁面,輸出了當前的時間,這很正常,當我們不斷的按F5刷新當前頁面的時候,我們會發現輸出的時間並沒有改變,甚至在Page_Load方法體內斷點也不會進來,這證明了並沒有執行后台函數,當10秒鍾過去了,時間也被更新出來了。
我們現在所要想做的是,在這10秒鍾的緩存期過期之前,用我們的辦法來更新頁面緩存。
Step1:修改指令,增加 VaryByCustom 屬性
<%@ OutputCache Duration="10" VaryByParam="none" VaryByCustom="Index_Key" %>
Step2:新建一個全局應用程序文件Global.asax,並且重寫GetVaryByCustomString 方法
public override string GetVaryByCustomString(HttpContext context, string custom) { if (custom == "Index_Key") { var flag = context.Cache["Index_Key"]; if (flag == null) { flag = DateTime.Now.Ticks; context.Cache["Index_Key"] = flag; } return flag.ToString(); } return base.GetVaryByCustomString(context, custom); }
Step3:更新OutputCache的操作
/// <summary> /// 更新OutputCache /// </summary> protected void btn_UpdateOutputCache_Click(object sender, EventArgs e) { HttpRuntime.Cache.Remove("Index_Key"); }
效果如下圖,刷新頁面,在緩存里的時間是42秒,
按照上面的例子,10秒鍾內,緩存時間應該都是42秒才對的,現在我們增加了更新OutputCache的功能,點擊一下,緩存里的時間被更新了,證明我們這個更新OutputCache是成功的!!
二、MVC
在MVC中,也有OutputCache,只是不像WebForm那樣,在前端頁面增加指令,而是在Controller里的Action增加Attribute,下面代碼演示了Index這個Action緩存10秒鍾,也就是說,10秒鍾之內,並不會執行這個Action,而是直接使用緩存。
public class HomeController : Controller { [OutputCache(Duration = 10)] public ActionResult Index() { ViewBag.DateTime = DateTime.Now; return View(); } }
View層就簡單的打印出來
@{ Layout = null; } <!DOCTYPE html> <html> <head> <title>Index</title> </head> <body> <div> @ViewBag.DateTime </div> </body> </html>
效果如下圖:不斷刷新頁面,十秒鍾之后,時間被更新了。
MVC更新OutputCache的思路其實跟WebForm一樣,所以這里不再重復了,文章末尾我會給出源碼和參考文獻,在這里,我想說說我自己對指令中的VaryByCustom屬性和重寫的方法GetVaryByCustomString的理解,官方的解釋很生澀或者不是很詳細,所以,還是自己理解比較好。
我找到MSDN上關於VaryByCustom的兩處解釋:
1、
VaryByCustom
任何表示自定義輸出緩存要求的文本。 如果特性的賦值為 browser,緩存將隨瀏覽器名稱和主要版本信息的不同而異。 如果輸入自定義字符串,則必須在應用程序的 Global.asax 文件中重寫 GetVaryByCustomString 方法。
2、
若要以聲明方式設置自定義字符串,請在 @OutputCache 指令中包括 VaryByCustom 屬性,並將該屬性設置為您要作為進行不同輸出緩存行為的依據的字符串。
也就是說,如果指令當中,使用了VaryByCustom,你的頁面緩存就會根據你重寫方法GetVaryByCustomString 中的返回的字符串的變化決定是否要更新頁面緩存。
我們再來看看GetVaryByCustomString 方法。(再貼一次,這個方法你可以參考MSDN上的做法,我這里是使用了自定義緩存來保存時間,清除OutputCache的操作會清空這個緩存,緩存失效了,就會賦予新的時間,VaryByCustom接受到新的字符串,它也就會知道去更新OutputCache了)
public override string GetVaryByCustomString(HttpContext context, string custom) { if (custom == "Index_Key") //每個設置了VaryByCustom屬性的頁面都會進來這個方法,custom為該指令的值 { var flag = context.Cache["Index_Key"]; //獲取自定義緩存中的標示,這里我使用了緩存,你也可以使用別的方法 if (flag == null) //假如是第一次進來,或者自定義緩存被清空了,就會走下面的方法體 { flag = DateTime.Now.Ticks; //將當前最新時間賦予緩存 context.Cache["Index_Key"] = flag; } return flag.ToString(); //返回最新時間字符串,頁面指令VaryByCustom接受到最新的字符串,發現跟上次的不同,就會更新OutputCache } return base.GetVaryByCustomString(context, custom); }
這里想要說的是,我重寫方法體里的時間跟頁面輸出的時間是沒有關系的,這里的時間純粹的為了作一個版本的迭代標識,這里我再貼一個MSDN給出的例子,根據請求瀏覽器的次版本進行緩存。
public override string GetVaryByCustomString(HttpContext context, string arg) { if(arg == "minorversion") { return "Version=" + context.Request.Browser.MinorVersion.ToString(); } return base.GetVaryByCustomString(context, arg); }
參考文章:
@ OutputCache
OutputCacheProfile.VaryByCustom 屬性
緩存用戶控件輸出的多個版本
如何:使用自定義字符串對頁的各個版本進行緩存
ASP.Net 更新頁面輸出緩存的幾種方法(包括用戶控件,iframe,頁面緩存等)