缓存篇(Cache)~第三回 HttpModule实现网页的文件级缓存
再写完缓存篇第一回之后,得到了很多朋友的好评和来信,所以,决定加快步伐,尽快把剩下的文章写完,本篇是第三回,主要介绍使用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这种文件时,要用绝对路径的形式。
没有用绝对路径时
用了绝对路径后
怎么样,这种文件级缓存的方式大家都掌握了吧!
分类:
其它 / 系统架构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2012-10-09 将不确定变为确定~头压缩是否有必要,MVC如何实现头压缩