標籤:style blog http color io os 使用 ar for
返回目錄
再寫完緩衝篇第一回之後,得到了很多朋友的好評和來信,所以,決定加快步伐,儘快把剩下的文章寫完,本篇是第三回,主要介紹使用HttpModule實現的檔案級緩衝,在看本文之前,大家需要限度HttpModule有一個瞭解,可以先看我的這篇文章《開發人員應該對IIS理論層的知識瞭解的多一些~第四講 HttpModule中的幾大事件》
對於檔案級緩衝來說,我們要知道兩點,一為檔案的URL,二為檔案的
下面是HttpModuleCache的核心代碼
/// <summary> /// CacheHttpModule類 /// </summary> internal class CacheHttpModule : IHttpModule { public void Dispose() { } private List<string> listNeedCacheExtend; private string stringClearCache = "zzl";//網域名稱中第一段 url 如果是此字元,則表示此次請求是清除緩衝 如: http://www.domain.com/zzl/******* public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState); listNeedCacheExtend = new List<string>(); string extends = WebConfig.GetUserSection("CacheInfo", "ExtendTypes", ".html|.htm"); foreach (string s in extends.Split(‘|‘)) { if (!string.IsNullOrEmpty(s) && !listNeedCacheExtend.Contains(s.Trim())) listNeedCacheExtend.Add(s.Trim()); } } public void context_BeginRequest(object sender, EventArgs e) { var application = (HttpApplication)sender; if (IsNeedCache(application)) //檢測當前請求是否需緩衝 { string key = string.Empty; ; string extend = VirtualPathUtility.GetExtension(application.Context.Request.FilePath).ToLower(); if (IsClearCache(application, out key)) { if (CacheManage.Container(key, extend))//緩衝中存在,則清除緩衝,結束請求 { application.Context.Response.Write(CacheManage.Remove(key, extend)); } application.CompleteRequest(); } else { #region 使用頁面壓縮 ResponseCompressionType compressionType = this.GetCompressionMode(application.Context.Request); if (compressionType != ResponseCompressionType.None) { application.Context.Response.AppendHeader("Content-Encoding", compressionType.ToString().ToLower()); if (compressionType == ResponseCompressionType.GZip) { application.Context.Response.Filter = new GZipStream(application.Context.Response.Filter, CompressionMode.Compress); } else { application.Context.Response.Filter = new DeflateStream(application.Context.Response.Filter, CompressionMode.Compress); } } #endregion if (CacheManage.Container(key, extend))//緩衝中存在,則直接返回內容,結束請求 { CacheManage.Write(application, key); application.CompleteRequest(); } } } } /// <summary> /// 檢測當前請求是否需緩衝,如果是則將此次結果添加至緩衝,如果此次請求出錯,不會執行至此 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void context_ReleaseRequestState(object sender, EventArgs e) { var application = (HttpApplication)sender; if (application.Context.Response.StatusCode == 200) { string strT = null; string extend = VirtualPathUtility.GetExtension(application.Context.Request.FilePath).ToLower(); if (IsNeedCache(application) && !IsClearCache(application, out strT)) { string key = application.Context.Request.Url.AbsoluteUri; //是否需要添加緩衝, if (!CacheManage.Container(key, extend)) { application.Context.Response.Filter = new ResponseFilter(application.Context.Response.Filter, key, extend, application.Context.Response.ContentEncoding); } } } } public void context_EndRequest(object sender, EventArgs e) { var application = (HttpApplication)sender; string key = application.Context.Request.Url.AbsoluteUri; application.Context.Response.Write("<Br>CacheMdule EndRequest"); } /// <summary> /// 檢測當前請求類型(url副檔名)確定是否需緩衝 /// 如果類型需緩衝,但副檔名是html或htm且存在相對應的物理檔案的,不執行快取作業 /// </summary> /// <param name="strFilePath"></param> /// <returns></returns> private bool IsNeedCache(HttpApplication application) { bool boolNeedCache = false; string stringExtend = VirtualPathUtility.GetExtension(application.Context.Request.FilePath).ToLower(); if (null != listNeedCacheExtend) //url副檔名是否滿足條件 { boolNeedCache = listNeedCacheExtend.Contains(stringExtend); } if (boolNeedCache) { if (stringExtend == ".html" || stringExtend == ".htm") { if (System.IO.File.Exists(application.Context.Request.PhysicalPath)) //存在對應物理檔案 { boolNeedCache = false; } } } return boolNeedCache; } /// <summary> /// 檢測當次請求是否是清除緩衝的 /// True 清除緩衝 False 不是清除緩衝的 /// </summary> /// <param name="application"></param> /// <param name="url">真實的URL地址</param> /// <returns></returns> private bool IsClearCache(HttpApplication application, out string url) { bool boolClearCache = false; url = application.Context.Request.Url.AbsoluteUri; string domain = application.Context.Request.Url.Host; Regex regex = new Regex("http://" + domain + "/" + stringClearCache + "/", RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase); if (regex.IsMatch(url)) { boolClearCache = true; url = "http://" + domain + "/" + url.Replace(regex.Match(url).Captures[0].Value, string.Empty); } return boolClearCache; } /// <summary> /// 擷取用戶端支援的壓縮類型 /// </summary> /// <param name="request"></param> /// <returns></returns> private ResponseCompressionType GetCompressionMode(System.Web.HttpRequest request) { string acceptEncoding = request.Headers["Accept-Encoding"]; if (string.IsNullOrEmpty(acceptEncoding)) return ResponseCompressionType.None; acceptEncoding = acceptEncoding.ToUpperInvariant(); if (acceptEncoding.Contains("GZIP")) return ResponseCompressionType.GZip; else if (acceptEncoding.Contains("DEFLATE")) return ResponseCompressionType.Deflate; else return ResponseCompressionType.None; } private enum ResponseCompressionType { None, GZip, Deflate } }
對於上面的HttpModule來說,還需要在config檔案中進行相應的配置,代碼如下
<modules runAllManagedModulesForAllRequests="true" > <add name="CacheHttpModule" type="HttpModuleCache.CacheHttpModule,HttpModuleCache"/> </modules>
程式運行後當檢測到合法的檔案後(如你之前對html和shtml結尾的檔案進行緩衝),就會組建檔案到伺服器的指定位置,下次訪問時,直接通過URL產生的伺服器本地路徑,將靜態檔案返回到用戶端即可,不過,有個地方要注意,由於這種方法產生的快取檔案,它的位置不是固定的,所以,在引用CSS,JS這種檔案時,要用絕對路徑的形式。
沒有用絕對路徑時
用了絕對路徑後
怎麼樣,這種檔案級緩衝的方式大家都掌握了吧!
下載完整HttpModuleCache項目
返回目錄
緩衝篇(Cache)~第三回 HttpModule實現網頁的檔案級緩衝