Spring学习笔记(杂谈):springboot applicaiton.properties设置全局静态资源缓存注意事项


1、背景

页面的打开速度有些慢,并且几乎所有的页面都关联js文件,有些还关联好几个,每次都下载这些文件比较浪费时间。并且这些js只有版本更新才会修改,所以平时打开页面时不用每次都下载js这些静态资源。

为了实现这个效果,我看了网上的很多方法,最后决定在application.properties设置,加上版本号控制,简单又方便。


2、操作步骤

项目使用的是spring boot,版本是5.1.2。

2.1、设置application.properties

先在application.properties中加入下面这些字段。

spring.resources.cache.period=604800
spring.resources.cache.cachecontrol.cache-public=true
spring.resources.cache.cachecontrol.no-cache=false
spring.resources.cache.cachecontrol.no-store=false
spring.resources.cache.cachecontrol.must-revalidate=false
spring.resources.cache.cachecontrol.max-age=604800

上面的这些字段可以在spring boot文档中了解具体效果。都是用来控制http header请求头来达到页面缓存的效果。
spring boot文档:https://docs.spring.io/spring-boot/docs/2.3.2.RELEASE/reference/htmlsingle/#cache-properties

这些字段设置有些冗余,比如spring.resources.cache.period会被spring.resources.cache.cachecontrol.max-age覆盖,默认情况下spring.resources.cache.cachecontrol.no-cache和spring.resources.cache.cachecontrol.no-store也都是false。不过不影响结果


2.2、设置版本控制

2.2.1、为什么设置版本控制

http的Cache-Control头设置的缓存主要是通过请求路径来进行缓存的,在浏览器本地建立key-value形式的缓存。其中,key是请求地址,value是资源。也就是说如果这次请求地址和以前的请求地址相同的话,那浏览器就不去访问服务器,直接从本地拿资源(也不是说一定不访问浏览器,不同的Cache-Control模式有不同的效果。这里的重点是通过请求地址来拿缓存)。

为了在版本更新,上线之后用户能立刻拿到最新的js等资源,我们在所有资源的请求地址后面加上额外的请求参数来区别新版本和旧版本的资源。比如上线之前某资源的请求地址是『www.cache.com/cache/test.js?v=1.0-20200101』,上线以后更新后面的请求参数,使新地址为『www.cache.com/cache/test.js?v=2.0-20200202』。这样浏览器就会认为两次请求是不同的资源,从而去请求最新的资源而不是去缓存拿旧资源。

这就是设置版本的原因。

2.2.2、如何设置版本控制

版本控制的具体设置可参考这篇文章:https://blog.csdn.net/qq_36036775/article/details/100163494



3、注意事项

3.1、请求地址不要带有动态参数

以前同事写的代码会在jsp引用的js的请求地址中加上一个随机数作为请求参数,比如下面这样

<script type="text/javascript" src="${context}/static/js/cache/test.js?rand=<%=Math.random()%>"></script>

目的很明显了,就是希望资源不要缓存。唉,时过境迁,现在又要缓存。总之,后面加了这个随机数就让浏览器每次都去请求资源,appliciation.properties的设置就完全没用了。所以后面的随机数一定要去掉。

3.2、请求地址的相对路径问题

3.2.1、结论

先说这个坑的结论。

如果applicaition.properties中没有设置spring.resources.static-locations属性。

请求静态资源时,比如jsp中引用js

<script type="text/javascript" src="${context}/static/js/cache/test.js"></script>

静态资源必须能以以下至少一个路径为根路径找到

  • classpath:/META-INF/resources/ + 请求地址相对路径
  • classpath:/resources/ + 请求地址相对路径
  • classpath:/static/ + 请求地址相对路径
  • classpath:/public/+ 请求地址相对路径

这四个情况是指spring.resources.static-locations的默认值,表示系统会将这四个路径作为静态资源的根地址。

在这里插入图片描述

spring boot文档中spring.resources.static-locations的描述


classpath是指代码编译后生成的target文件的classes目录

在这里插入图片描述

classes目录

以下面的例子为例

<script type="text/javascript" src="${context}/static/js/cache/test.js"></script>

这个js请求地址中的相对地址是『/static/js/cache/test.js』,那这个资源在target中的真正地址就应该是下面这样(剩下三种情况类推)

classpath:resources/static/js/cache/test.js

在这里插入图片描述

test.js应该在的位置





如果以spring.resources.static-locations配置的路径(默认以上四个)为资源根路径找不到资源,那系统还会以『classpath:/』为根路径去寻找资源,还找不到则404。但是要注意,如果以『classpath:/』为根路径找到了资源,那在application.properties上设置的cache-control是不会起作用的。

比如application.properties上设置了需要缓存静态资源,『public=true,max-age=604800』。并且没有设置spring.resources.static-locations。系统以『classpath:/』找到了资源,那这个静态文件不会缓存,Response Header仍然是『no-cache,no-store』。


3.2.2、原因

Spring 中所有的请求都会在ResourceHttpRequestHandler#handleRequest中处理。在5.1.2的源码中,473行的位置,有个方法叫prepareResponse。

在这里插入图片描述

prepareResponse在handleRequestz的使用位置

这个方法是用来设置Cache-Control的。在这里打个断点,如果系统以spring.resources.static-locations为根地址找到了资源,那点进这个方法看,可以看到方法中的this.cahceControl不为空,并且值就和我们在application.properties中设置的一样;如果系统是以『classpath:/』为根路径找到的资源,那点进方法后,会发现this.cache=null

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sinat_38393872/article/details/107938768