缓存篇(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这种文件时,要用绝对路径的形式。

没有用绝对路径时

用了绝对路径后

怎么样,这种文件级缓存的方式大家都掌握了吧!

下载完整HttpModuleCache项目

返回目录

时间: 2024-08-28 09:03:31

缓存篇(Cache)~第三回 HttpModule实现网页的文件级缓存的相关文章

缓存篇(Cache)~大话开篇

闲话杂淡 想写这篇文章很久了,但总是感觉内功还不太够,总觉得,要写这种编程领域里的心法(内功)的文章,需要有足够的实践,需要对具体领域非常了解,才能写出来.如今,感觉自己有写这种文章的能力了,所以,快马加鞭,把这个内功写出来,分享给大家,分享我的Fans! 缓存:缓存的领域很广泛,实现方法也很多,你可以使用文件,内存来实现缓存,而缓存的方法也有很多,对于一个网页来说,你可以缓存它的页面内容(HTML),或者缓存它的数据集(DataSet),这两种方式适用于不同的场合,对于需要主动触发的缓存,它可

Django2.2 Cache缓存的设计以及几种方式的 多级或单级缓存处理

首先照例说明一下缓存的作用以及Django中可以用到的缓存方式: 缓存的作用是用于数据项的再次加载,在设定的时间内可以无压力刷新或者再次访问该数据信息 方式一数据库缓存(Django原生的---有代码提示) 方式二(非Django原生)redis缓存------------------------------------------windows下的redis配置安装博客推荐 ----->  https://blog.csdn.net/AkiraNicky/article/details/825

Android volley 解析(四)之缓存篇

这是 volley 的第四篇 blog 了,写完这篇,volley 的大部分用法也都算写了一遍,所以暂时不会写 volley 的文章了,如果想看我前面写的文章,可以点这里 Android volley 解析(三)之文件上传篇 为什么要用缓存 我们知道,当客户端在请求网络数据的时候,是需要消耗流量的,特别是对于移动端用户来说,对于流量的控制要求很高.所以在做网络请求的时候,如果对数据更新要求不是特别高,往往都会用到缓存机制,一方面能减少对服务端的请求,控制流量:另一方面,当客户端在没有网络的情况下

mybatis13--2级缓存

验证内置的2级缓存 创建对应的dao public interface StudentDao { /** * 验证mybatis2级缓存! */ Student selectStudentById(Integer sId); } 创建对应的mapper文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3

.net缓存——基于文件的缓存

一,.Net中的缓存基础知识 .net中支持的两种依赖: CacheDependency SqlDependency 表示对于文件或者目录的依赖 表示对于SQL数据库的依赖 过期时间 绝对过期时间 滑动过期时间 一个特定的时间点,类型为DateTime 一个时间间隔,类型为TimeSpan 优先级  :   CacheItemPriority 由于我们需要缓存大量的数据,在内存有限的情况下,就必须对缓存的数据进行优先级分类,以便在需要的时候,将不重要的数据从缓存中移除.优先级用来指定缓存数据的重

手把手带你阅读Mybatis源码(三)缓存篇

前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读Mybatis源码(一)构造篇 和 手把手带你阅读Mybatis源码(二)执行篇,主要说明了MyBatis是如何将我们的xml配置文件构建为其内部的Configuration对象和MappedStatement对象的,然后在第二篇我们说了构建完成后MyBatis是如何一步一步地执行我们的SQL语句并且对结果集进行封装的. 那么这篇作为MyBatis系列的最后一篇,自然是要来聊聊MyBatis中的一个不可忽视的

ASP.NET缓存中Cache过期的三种策略

原文:ASP.NET缓存中Cache过期的三种策略 我们在页面上添加三个按钮并双击按钮创建事件处理方法,三个按钮使用不同的过期策略添加ASP.NET缓存. <asp:Button ID="btn_InsertNoExpirationCache" runat="server" Text="插入永不过期缓存"      OnClick="btn_InsertNoExpirationCache_Click" />   

缓存篇~第七回 Redis实现基于方法签名的数据集缓存(可控更新,分布式数据缓存)

返回目录 本篇文章可以说是第六回 Microsoft.Practices.EnterpriseLibrary.Caching实现基于方法签名的数据集缓存(可控更新,WEB端数据缓存)的续篇,事实上,有EnterpriseLibrary.Caching也只是实现缓存持久化的一种方式,而Redis做为成熟的分布式存储中间件来说,实现这个数据集缓存功能显得更加得心应手,也更加满足大型网站的设计规则.(在多web服务器时(web端实现负载均衡,反向代理),EnterpriseLibrary.Cachin

从Java视角理解CPU缓存(CPU Cache)

从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多. 其实在30年前, CPU的频率和内存总线的频率在同一个级别, 访问内存只比访问CPU寄存器慢一点儿. 由于内存的发展都到技术及成本的限制, 现在获取内存中的一条数据大概需要200多个CPU周期(CPU cycles), 而CPU寄存器一般情况下1个CPU周期就够了. CPU缓存 网页浏览器为了加