SpringBoot2.x配置静态文件缓存_springboot 来自内存缓存 200-程序员宅基地

技术标签: java  缓存  

HTTP浏览器缓存

对这部分知识不太熟悉的,可以先看一下这篇文章:HTTP浏览器缓存机制

配置文件yml配置

spring:
 resources:
   static-locations: classpath:/static/,classpath:/views/,classpath:/templates/
   chain:
      strategy:
        #MD5实现
        content:
          enabled: true
          paths: /**
        #版本号管理(与MD5实现方式同时存在时,需要指定不同的路径,来分别实现对应的文件管理)
        #fixed:
          # 开启版本控制策略,默认为false
          #enabled: true
          #paths: /**,/v1.0.0/**
          #version: v1.0.0
      cache: true
      compressed: false
      enabled: true
    #缓存
   cache:
      cachecontrol:
        cache-public: true
        # 缓存有效期 24小时
        max-age: 24h
      # 资源缓存时间,单位天,7天
      period: 7d

浏览器缓存的过程:
在这里插入图片描述

  1. 当第一次访问时,所有的静态资源文件没有缓存,需要请求服务下载对应的文件
  2. 当第二次页面加载时,因为我们开启了缓存,浏览器会判断是否有缓存
  3. 有缓存,需要判断,缓存是否过期,过期时间就是通过配置缓存有效期:max-age: 24h,实现的
  4. 如果没有过期,则静态文件直接读取浏览器缓存,不会向服务器重新访问资源在这里插入图片描述
  5. 如果没有缓存或者缓存已经过期,则需要请求服务器,并通过判断Last-Modified:响应资源的最后修改时间,是否更新,如果没有更新,返回304状态,读取浏览器缓存在这里插入图片描述
  6. 如果更新了,则说明该文件的再服务器端已经发生了改变,浏览器需要重新加载更新该文件
  7. 至此一个完整的浏览器缓存加载页面静态资源的过程就算完成了
  8. 当浏览器向服务器请求后,无论是没有更新,返回304,还是有更新,重新加载文件,新一轮的缓存有效期生成,也就是之前过期的有效期,现在又重新开始计算时间,此时再访问静态文件,会直接读取缓存,直到缓存再次过期,再进行下一次的循环。
  9. 我的配置中没有使用Etag,因为它需要很多的md5运算,消耗较多的内存,我觉得我的系统暂时可以不需要这一层

静态资源版本控制

Spring 默认提供了静态资源版本映射的支持。
当我们的资源内容发生改变时,由于浏览器缓存,用户本地的资源还是旧资源,为了防止这种情况发生导致的问题。我们可能会选择在资源文件后面加上参数“版本号”或其他方式。

时间戳实现

在htnl中一如静态文件时,加一个时间戳的后缀,每次加载时间戳是不一样的,这样能保证浏览器每次都向服务器重新请求加载

<script>
    document.write('<script type="text/javascript" src="script/basicschema/common.js?v=' + Date.now() + '"><\/script>');
</script>
<script>
    document.write('<script type="text/javascript" src="script/basicschema/basicdata/energyUnit.js?v=' + Date.now() + '"><\/script>');
</script>

在这里插入图片描述

MD5实现

首先在application.yml配置(在最上边的配置文件内容中已经有了)

spring:
 resources:
   chain:
      strategy:
        #MD5实现
        content:
          enabled: true
          paths: /**

其次,如果您恰巧和我一样使用Thymeleaf作为模板引擎,则可以和我一样使用@bean语法直接从模板访问ResourceUrlProvider bean。

<script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/common.js')}}"></script>
<script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/benchmark/benchmarkItem.js')}}"></script>

在这里插入图片描述
注意:如果你的js文件没有修改,或者修改没重启,MD5的值可能不会改变,当你重启服务后你会看到你修改过后的文件MD5也随之改变了。

简单看了下源代码,MD5的计算是通过 ContentVersionStrategy 这个类实现的。此VersionStrategy实现根据资源的内容计算MD5哈希值,并将其附加到文件名后面,也就是你不改变内容MD5值是不会变的

这种方式类似于Etag的方式,只不过,我们可以自主控制对哪些文件进行md5计算。

问题:使用ControllerAdvice这种方式,我尝试了以后,不能用,html中使用urls,报错,不识别,不知道什么原因,(有知道原因的可以告知一下)代码如下:

@ControllerAdvice
public class ControllerConfig {
    
    @Autowired
    ResourceUrlProvider resourceUrlProvider;

    @ModelAttribute("urls")
    public ResourceUrlProvider urls() {
    
        return this.resourceUrlProvider;
    }
}
<script type="text/javascript" th:src="@{${urls.getForLookupPath('/script/basicschema/benchmark/benchmarkItem.js') }}"></script>

这样写,就不行,页面会报错,不识别urls

版本号实现

在application.yml或者application.properties中增加配置文件

spring:
 resources:
   static-locations: classpath:/static/,classpath:/views/,classpath:/templates/
   chain:
      strategy:
        #版本号管理(与MD5实现方式同时存在时,需要指定不同的路径,来分别实现对应的文件管理)
        fixed:
          enabled: true
          paths: paths: /**,/v1.0.0/**
          version: v1.0.0

其次,如果您恰巧和我一样使用Thymeleaf作为模板引擎,则可以和我一样使用@bean语法直接从模板访问ResourceUrlProvider bean。

<script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/common.js')}}"></script>
<script th:src="@{ ${@mvcResourceUrlProvider.getForLookupPath('/script/basicschema/benchmark/benchmarkItem.js')}}"></script>

正常来说,配置了相应的映射路径,则系统便会在文件路径最前面加上相应的版本号,当我们每次修改只需要更新版本号的设置,客户端就会自动请求最新的数据了。
同样的看了下此VersionStrategy的实现是FixedVersionStrategy类,来使固定版本字符串作为资源路径的前缀。在这里插入图片描述
如图,文件的路径最前面会加上对应的版本号

总结

通过以上的配置,我们就可以做到即可以对一些第三方或者不会变的静态文件进行缓存,减少每次加载文件的访问量,又可以对一些需要经常更改和变化的文件实现了单独的控制,保证他可以及时更新,而不会一直是缓存文件。
当然不知道是不是因为用的是SpringBoot2.x的原因,从网上翻阅资料查到的一些实现方式,在我的系统里似乎有些方法和配置不好用,如果知道问题在哪的朋友,还望指点迷津。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xue317378914/article/details/106638326

智能推荐

NOIP算法概论-程序员宅基地

文章浏览阅读443次。之前高一参加比赛前,曾写过总结,主要是提醒自己NOIP所需要的基本算法,以及至少所需要掌握的数据结构。当然,NOIP,最重要的算法,只有一个,THAT IS “搜索大法”练好了搜索,今后的所有竞赛,题目哪怕拿不了满分,至少30+,说不定60+。自己脑补一下优化,100分就到手啦。。。第一篇正儿八经的博客(别管前面那篇):请各位OIER们,一定一定,要练习搜索,必须练习搜索,而且搜索MU...

用gcc编译器实现PC编程_gcc怎么使用pc文件-程序员宅基地

文章浏览阅读619次。1、下载gcc编译器2、配置系统环境变量3、创建项目文件夹4、dos窗口进行转换和编译5、使用文件进行调用环境变量6、生成可执行文件_gcc怎么使用pc文件

Windows平台上的5种敏捷软件开发(过程)模型_敏捷模型-程序员宅基地

文章浏览阅读1.4k次。Windows平台上的5种敏捷软件开发(过程)模型_敏捷模型

软考高项 : (05)论信息系统项目的风险管理_项目同其他经济活动一样存在风险,项目管理者必须对风险实施有效的管理。项目风险-程序员宅基地

文章浏览阅读2.5k次,点赞4次,收藏12次。5[论文]论信息系统项目的风险管理项目同其他经济活动一样存在风险,项目管理者必须对风险实施有效的管理,项目风险管理包活进行风险管理计划编制,对项目风险通行识别,分析,应对和监控的过程,完全避免或者消除风险,或者只享受权益而不承担风险,是不可能的,主要风险清单是一个重要的风险管理工具,它指明了项目在任何时候面临的最大风险,是不可能的。通过对主要风险进行追踪并建立应对措施。可以使项目经理保持较强的风..._项目同其他经济活动一样存在风险,项目管理者必须对风险实施有效的管理。项目风险

【算法4】--- 栈(python)_python stack-程序员宅基地

文章浏览阅读3.3k次,点赞7次,收藏36次。栈(stack)是限定仅在表尾进行插入和删除操作的线性表。栈是后进先出(Last In First Out, LIFO)的_python stack

大学生本科计算机专业毕业设计 11基于协同过滤算法商品推荐系统-程序员宅基地

文章浏览阅读87次。【代码】大学生本科计算机专业毕业设计 11基于协同过滤算法商品推荐系统。

随便推点

我的WCF之旅(10):如何在WCF进行Exception Handling-程序员宅基地

文章浏览阅读67次。在任何Application的开发中,对不可预知的异常进行troubleshooting时,异常处理显得尤为重要。对于一般的.NET系统来说,我们简单地借助try/catch可以很容易地实现这一功能。但是对于 一个分布式的环境来说,异常处理就没有那么简单了。按照面向服务的原则,我们把一些可复用的业务逻辑以Service的形式实现,各个Service..._wcf exception.type

iOS 直播技术及Demo_ios直播懂的-程序员宅基地

文章浏览阅读1.4w次,点赞4次,收藏24次。要过年了,新年快乐,今天写一些关于iOS直播技术相关知识,及详细Demo介绍,首先请下载DemoDemo下载地址(点击跳转下载)一.直播介绍1.1.直播现状近年来,直播越来越火,但直播技术却对软件开发人员技术要求很高,因为直播中运用到的技术难点非常之多,视频/音频处理,图形处理,视频/音频压缩,CDN分发,即时通讯等技术,个人很难开发出来。但现在已经有了各个领域的大神,封装出了各种牛逼..._ios直播懂的

浅谈深度学习_深度学习csdn-程序员宅基地

文章浏览阅读6.6k次。1 绪论机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等学科。专门研究计算机如何模拟或者实现人类的学习行为,来获取新的知识或技能,并重组已有的知识结构使之不断改善自身的性能。他是人工智能核心,是使计算机具有智能的根本途径。深度学习(DL,Deep Learning)是机器学习(ML,Machine Learning)领域中一个新的研究方向,他被引入机器学习使其更接近于最初的目标——人工智能(AL,Aritifical Intelligence)。2 深度学习的发展1_深度学习csdn

_ZN10tensorflow8internal21CheckOpMessageBuilder9NewStringEv_undefined symbol: _zn10tensorflow8internal21checko-程序员宅基地

文章浏览阅读628次。undefined symbol: _ZN10tensorflow8internal21CheckOpMessageBuilder9NewStringEv这是一类错误。问题的指向编译没有编译成功。前面的错误tensorflow.python.framework.errors_impl.NotFoundError: /home/wjay/deeplearning/PU-GAN/PU-GAN-master/tf_ops/sampling/tf_sampling_so.so:这是告诉你哪个文件没有编.._undefined symbol: _zn10tensorflow8internal21checkopmessagebuilder9newstringe

【深度学习】基于PyTorch搭建ResNet18、ResNet34、ResNet50、ResNet101、ResNet152网络_resnet34 resnet101-程序员宅基地

文章浏览阅读7k次,点赞15次,收藏157次。所有不同层数的ResNet:这里给出了我认为比较详细的ResNet18网络具体参数和执行流程图:这里并未采用BasicBlock和BottleNeck复现ResNet18具体ResNet原理细节这里不多做描述,直接上代码model.py网络模型部分:train.py训练部分(使用CIFAR10数据集):3. 训练测试结果训练损失:每一个epoch结束之后的测试:训练时多次修改超参数,最后经过30次epoch之后的测试准确度达到了0.7471,没有在训练下去也没有明显提升,初学深度神经网络,_resnet34 resnet101

C语言数组大小-程序员宅基地

文章浏览阅读4.9k次,点赞2次,收藏9次。通过sizeof()函数得到C语言数组长度_c语言数组大小

推荐文章

热门文章

相关标签