1、直接在.aspx頁面中設置
最直接的,在.aspx頁面中添加一行如下代碼:
<%@ OutputCache Duration="3600" VaryByParam="None" %>
表示將這個頁面緩存1小時。運行頁面查看請求頭信息:
第一次運行,效果如圖:
再次請求頁面
點擊“轉到”或者光標移入地址欄然后回車,或者F5刷新頁面,效果如圖:
注意:緩存對ctrl+F5強刷不起作用。
可以看到,設置后請求響應頭中多了max-age、Expires、Last-Modified這三個屬性,並且Http狀態碼也由200變成了304,說明我們成功設置了該頁面的緩存。
對比兩次請求頭里的Cache-Control,發現第一次是no-cache,第二次是max-age=0,並且第三、第四。。次都是max-age=0,關於Cache-Control值的說明如下:
如果no-cache出現在請求中,則代表瀏覽器要求服務器,此次請求必須重新返回最新文件(請求完成后,你會看到http狀態碼是200);如果max-age=0出現在響應中,則代表服務器要求瀏覽器你在使用本地緩存的時候,必須先和服務器進行一遍通信,將etag、 If-Not-Modified等字段傳遞給服務器以便驗證當前瀏覽器端使用的文件是否是最新的(如果瀏覽器用的是最新的文件,http狀態碼返回304,服務器告訴瀏覽器使用本地緩存即可;否則返回200,瀏覽器得自己吧文件重新下載一遍)。
請求頁面方式說明:
首次請求 | 返回狀態碼200,顯然得到全部正文。 |
F5 | 刷新,對Last-Modified有效,它是讓服務器判斷是否需要讀取緩存,所以,依然存在請求和返回數據。狀態碼是304。 |
點擊“轉到”或者光標移入地址欄然后回車 | 對Cache-Control有效,是瀏覽器自己決定是否讀取緩存,如果在緩存期限內,瀏覽器不會向WEB服務器發送請求,我們可以看到send和receive的數據全部是0。無交互,故無狀態碼。 |
ctrl+f5 | 相當於是強制刷新,所以狀態碼200 OK,返回全部正文數據。 |
2、在.cs代碼中設置
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace HttpTest { public partial class HttpTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { try { int intHttpCacheMaxAge = 0; //瀏覽器緩存時間,單位:秒 string strHttpCacheMaxAge = ConfigurationManager.AppSettings["httpCacheMaxAge"]; if (!string.IsNullOrEmpty(strHttpCacheMaxAge)) { intHttpCacheMaxAge = Convert.ToInt32(strHttpCacheMaxAge); } //設置緩存過期變量,默認為緩存時間多1秒,即第一次請求總讓它返回200 int seconds = intHttpCacheMaxAge + 1; DateTime? IfModifiedSince = null; if (!string.IsNullOrEmpty(Request.Headers["If-Modified-Since"])) { IfModifiedSince = Convert.ToDateTime(Request.Headers["If-Modified-Since"]); seconds = (DateTime.Now - Convert.ToDateTime(IfModifiedSince)).Seconds; } if (seconds > intHttpCacheMaxAge) { Common.Common.currDateTime = DateTime.Now; Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.SetExpires(Convert.ToDateTime(Common.Common.currDateTime).AddSeconds(intHttpCacheMaxAge)); Response.Cache.SetLastModified(Convert.ToDateTime(Common.Common.currDateTime)); } else { Response.Status = "304 Not Modified.."; Response.StatusCode = 304; Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.SetExpires(Convert.ToDateTime(Common.Common.currDateTime).AddSeconds(intHttpCacheMaxAge)); Response.Cache.SetLastModified(Convert.ToDateTime(Common.Common.currDateTime)); ////上面設置了響應請求狀態為304后,我們不希望再繼續執行其他的業務邏輯了,所以, ////要阻止后續代碼的執行,有以下兩種方法: ////方法一:使用CompleteRequest()方法直接執行EndRequest事件,如: //HttpApplication app = (HttpApplication)sender; //app.CompleteRequest(); ////方法二:使用return跳出代碼執行,不執行return后面的任何代碼,如: return; } } catch (Exception ex) { Response.Write("異常!" + ex); } } } }
配置文件:
<!--設置瀏覽器緩存時間,單位:秒--> <add key="httpCacheMaxAge" value="10"/>
這種方法可以針對單個頁面設置,比較靈活。
3、利用HttpModule和HttpWorkerRequest設置
相比前兩種,這種方法效率高些。
為了利用HttpModule,所以我們先要創建一個實現了IHttpModule接口的類,如:
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Web; namespace HttpTest.Module { public class HttpCacheModule:IHttpModule { public void Init(HttpApplication context) { context.EndRequest += context_EndRequest; } void context_EndRequest(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender; IServiceProvider provider = (IServiceProvider)app.Context; HttpWorkerRequest worker = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); int intHttpCacheMaxAge = 0; //瀏覽器緩存時間,單位:秒 string strHttpCacheMaxAge = ConfigurationManager.AppSettings["httpCacheMaxAge"]; if (!string.IsNullOrEmpty(strHttpCacheMaxAge)) { intHttpCacheMaxAge = Convert.ToInt32(strHttpCacheMaxAge); } //設置緩存過期變量,默認為緩存時間多1秒,即第一次請求總讓它返回200 int seconds = intHttpCacheMaxAge+1; DateTime? IfModifiedSince = null; if (app.Context.Request.Headers["If-Modified-Since"]!=null) { IfModifiedSince = Convert.ToDateTime(app.Context.Request.Headers["If-Modified-Since"]); seconds = (DateTime.Now - Convert.ToDateTime(IfModifiedSince)).Seconds; } if (seconds > intHttpCacheMaxAge) { Common.Common.currDateTime = DateTime.Now; } else { app.Context.Response.Status = "304 Not Modified.."; app.Context.Response.StatusCode = 304; } worker.SendKnownResponseHeader(HttpWorkerRequest.HeaderCacheControl, "public"); worker.SendKnownResponseHeader(HttpWorkerRequest.HeaderExpires, Convert.ToDateTime(Common.Common.currDateTime).AddSeconds(intHttpCacheMaxAge).ToUniversalTime().ToString("r")); worker.SendKnownResponseHeader(HttpWorkerRequest.HeaderLastModified, Convert.ToDateTime(Common.Common.currDateTime).ToUniversalTime().ToString("r")); } public void Dispose() { } } }
配置文件:
IIS6中按以下配置: <system.web> <httpModules> <add name="HttpCacheModule" type="HttpTest.Module.HttpCacheModule,HttpTest"/> </httpModules> </system.web> IIS7及后續版中本: <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <add name="HttpCacheModule" type="HttpTest.Module.HttpCacheModule,HttpTest"/> </modules> </system.webServer>
另外,為了保存當前時間做緩存過期判斷,所以定義一個靜態變量,如:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace HttpTest.Common { public static class Common { public static DateTime? currDateTime = null; } }
並且在Global文件的Application_Start方法中初始化它,如:
void Application_Start(object sender, EventArgs e) { Common.Common.currDateTime = DateTime.Now; }
這種方式適合對所有頁面都有效,適合批量設置。
參考資料:
https://www.cnblogs.com/fish-li/archive/2012/01/11/2320027.html
https://segmentfault.com/q/1010000002578217
https://www.cnblogs.com/ajunForNet/archive/2012/05/19/2509232.html
https://www.cnblogs.com/futan/archive/2013/04/21/cachehuancun.html
https://www.cnblogs.com/yuanyuan/p/4921717.html(HttpModule詳解)
http://www.cnblogs.com/yuanyuan/archive/2010/11/15/1877709.html
http://www.cnblogs.com/luminji/archive/2011/09/14/2174751.html
http://www.cnblogs.com/luminji/archive/2011/09/13/2172737.html