如何在SpringBoot中设置HTTP缓存,你知道么?

news2025/1/31 3:16:24

在工作之余阅读缓存相关的书籍时,看到了http缓存相关的知识,HTTP 缓存机制是一个 web 性能优化的重要手段,无论是做前端还是做web后台,都可能会用得到它,应该是知识体系库中的一个基础环节,以前这一块学的不是很扎实,现在整理资料巩固巩固。

HTTP缓存可以说是浏览器缓存的其中一种,浏览器缓存也包含很多内容:HTTP 缓存、indexDB、cookie、localstorage 等等。这里我们只讨论 HTTP 缓存相关内容。

浏览器主要分为Last-Modified/EtagCache-Control/Expires

其中Cache-Control/Expires属于强缓存,Last-Modified/Etag属于协商(比较)缓存

cache-control


cache-control字段位于这里,像这样设置的cache-control是没有缓存的

在请求中使用Cache-Control 时,它可选的值有:

在响应中使用Cache-Control 时,它可选的值有:

Cache-Control 中,这些值可以自由组合,多个值如果冲突时,也是有优先级的,而no-store优先级最高。

cache-control这种强缓存是性能高的,它不需要请求服务器,就直接从本地加载文件了,后面的Last-Modified/Etag是需要请求服务器来验证文件的。

在实际使用中,浏览器会先验证强缓存,所以对于js、css、img文件的过期时间可以设置非常长,因为前端构建工具打包出来的文件是有利于缓存的,比如可以配置webpack打包后的js文件跟个hash值,就可以根据hash来判断文件是否发生变化。在打包出来的文件名上加上文件内容的hash是目前最常见的有效使用浏览器强缓存的方法,js文件如果有内容更新,hash就会更新,浏览器请求路径变化所以更新缓存,如果js内容不变,hash不变,直接用缓存,下面的etag也有类似的思想。

如果对于变化频繁的文件就不要加cache-control,如果配置cache-control的过期时间比较长的话,由于cache-control优先级比Last-Modified/Etag高,所以会在过期时间内不会更新文件。

Expires


关于Expires:

  • Expires 是以前用来控制缓存的http头,Cache-Control是新版的API。

  • 现在首选 Cache-Control。

  • 如果在Cache-Control响应头设置了 “max-age” 或者 “s-max-age” 指令,那么 Expires 头会被忽略。

  • 响应头设置方式:Expires: Wed, 21 Oct 2015 07:28:00 GMT

  • Expires 响应头包含日期/时间, 即在此时候之后,响应过期。

注意:因为过期标准的时间用的是本地时间,所以不靠谱,所以要使用Cache-Control代替Expires。

关于第三点:一般会把Cache-Control和Expires都设置上,因为 Expires 是 HTTP 1.0 定义的字段,而 Cache-Control 是 HTTP 1.1 的字段,万一客户端只支持 HTTP 1.0,那么 Cache-Control 有可能就会不工作,所以一般为了兼容会都写上。

Cache-Control设置时间长度、Expires 设置时间点

Last-Modify/If-Modify-Since


浏览器第一次请求一个资源的时候,服务器返回的 header中会加上Last-ModifyLast-modify是一个时间标识该资源的最后修改时间。

当浏览器再次请求该资源时,发送的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。

如果命中缓存,则返回http304,并且不会返回资源内容,并且不会返回Last-Modify。由于对比的服务端时间,所以客户端与服务端时间差距不会导致问题。但是有时候通过最后修改时间来判断资源是否修改还是不太准确(资源变化了最后修改时间也可以一致)。于是出现了ETag/If-None-Match

Etag/If-None-Match


经过上面的缓存后,若未命中强缓存,则浏览器会将请求发送至服务器。服务器根据http头信息中的Last-Modify/If-Modify-SinceEtag/If-None-Match来判断是否命中协商缓存。如果命中,则http返回码为304,浏览器从缓存中加载资源。

Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。

ETag是HTTP1.1中才加入的一个属性,用来帮助服务器控制Web端的缓存验证。它的原理是这样的,当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器,浏览器把"3f80f-1b6-3e1cb03b" 和 A 同时缓存在本地,当下次再次向服务器请求A时,会通过类似 If-None-Match: “3f80f-1b6-3e1cb03b” 的请求头把ETag发送给服务器,服务器再次计算A的哈希值并和浏览器返回的值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端。

HTTP中并没有指定如何生成Etag,可以自己定义一种好的方式来生成Etag

通过etag,实际上还是要向服务器发送一次请求,但是把资源文件缓存下来了,减少服务器带宽。

总结

Last-Modified与 Etag对比

你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  • Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间。

  • 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存。

  • 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

浏览器第一次和第二次请求对比,这张图反映出优先级:ETag优先级 > Last-Modified优先级、cache-control优先级 > expires优先级。

用户操作与缓存

在spring boot中开启http缓存

=====================

本地测试环境:

  • Spring boot版本: 2.1.3.RELEASE

  • 项目前后端通过ajax交互,前端文件全部放在src/main/resources/static目录下,跟后台一起部署。

实操:

配置Cache-Control

在spring boot中,发现没有经过http缓存相关的配置默认是这样子的,response带有不使用缓存的http头,导致每次加载都要从服务端获取数据,而有些静态资源文件是不必要每次从服务器去获取的,像常用的js库、css库什么的。

Spring boot配置cache-control和expires可以通过WebMvcConfigurationSupport来配置,也可通过修改配置文件的方式,这里使用配置类的方式。

这里需要注意的是,使用WebMvcConfigurationSupport会使WebMvcAutoConfiguration的自动配置不生效,因为WebMvcAutoConfiguration里面有个@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),表现为默认的一些映射路径无法访问,如果想保留默认的配置,那就使用implements WebMvcConfigurer的方式来配置

@Configuration

public class WebConfigConfigurer extends WebMvcConfigurationSupport {

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler(“/static/**”)

.addResourceLocations(“classpath:/static/”)

.setCacheControl(CacheControl.maxAge(604800, TimeUnit.SECONDS));

}

}

这里将src/main/resources/static目录映射到/static的url下,然后setCacheControl就可以了。

spring.resources.cache.cachecontrol.cache-private= # Indicate that the response message is intended for a single user and must not be stored by a shared cache.

spring.resources.cache.cachecontrol.cache-public= # Indicate that any cache may store the response.

spring.resources.cache.cachecontrol.max-age= # Maximum time the

response should be cached, in seconds if no duration suffix is not specified.

spring.resources.cache.cachecontrol.must-revalidate= # Indicate that once it has become stale, a cache must not use the response without re-validating it with the server.

spring.resources.cache.cachecontrol.no-cache= # Indicate that the cached response can be reused only if re-validated with the server.

spring.resources.cache.cachecontrol.no-store= # Indicate to not cache the response in any case.

spring.resources.cache.cachecontrol.no-transform= # Indicate intermediaries (caches and others) that they should not transform the response content.

spring.resources.cache.cachecontrol.proxy-revalidate= # Same meaning as the “must-revalidate” directive, except that it does not apply to private caches.

spring.resources.cache.cachecontrol.s-max-age= # Maximum time the response should be cached by shared caches, in seconds if no duration suffix is not specified.

spring.resources.cache.cachecontrol.stale-if-error= # Maximum time the response may be used when errors are encountered, in seconds if no duration suffix is not specified.

spring.resources.cache.cachecontrol.stale-while-revalidate= # Maximum time the response can be served after it becomes stale, in seconds if no duration suffix is not specified.

如果要使用配置的方式也很简单,上面这些是关于cache的配置,在spring boot官方文档最后的附录里面有。

再来测试,首先把缓存开启,它这个选项就是通过request headers里的CacheControl实现的。

然后刷新发现已经使用了http缓存。

发现已经不是之前默认的no-store了,而是变为我们自己设置的缓存过期时间了,说明已经在使用http的强缓存了!

小提示:这个addResourceHandleraddResourceLocations不要弄反了,addResourceHandler的参数是URL path patterns,addResourceLocations的参数是本地资源路径

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler(“/**”)

.addResourceLocations(“classpath:/static/”)

.setCacheControl(CacheControl.maxAge(0, TimeUnit.SECONDS)

.cachePublic());

}

像这种的,就是将src/main/resources/static目录映射到/的url下

如果遇到问题,那么就debug ResourceHandlerRegistry的AbstractHandlerMapping getHandlerMapping()方法,在urlMap变量中看到url与handler的映射关系

配置Last-Modified缓存

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler(“/static/**”)

.addResourceLocations(“classpath:/static/”)

.setCacheControl(

CacheControl.maxAge(0, TimeUnit.SECONDS)

.cachePublic());

}

如果遇到问题,那么就debug ResourceHandlerRegistry的AbstractHandlerMapping getHandlerMapping()方法,在urlMap变量中看到url与handler的映射关系

配置Last-Modified缓存

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler(“/static/**”)

.addResourceLocations(“classpath:/static/”)

.setCacheControl(

CacheControl.maxAge(0, TimeUnit.SECONDS)

.cachePublic());

}

}

如果遇到问题,那么就debug ResourceHandlerRegistry的AbstractHandlerMapping getHandlerMapping()方法,在urlMap变量中看到url与handler的映射关系

配置Last-Modified缓存

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler(“/static/**”)

.addResourceLocations(“classpath:/static/”)

.setCacheControl(

CacheControl.maxAge(0, TimeUnit.SECONDS)

.cachePublic());

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/89179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TAPD新增需求自动写入腾讯文档

【实现效果:】TAPD新增需求/缺陷,可以自动写入腾讯文档智能表,方便通过腾讯文档灵活管理自己的项目排期,并且通过不同的视图效果,实现简单的需求统计/分组迭代,通过数据关联及时跟进延期项目。 【准备工作…

引用类型 - JavaScript 数组对象、遍历、复制、冒泡排序、选择排序、数组方法、数组去重

写在前面 哎呀呀,每次都是要沉淀好久好久才能更一篇文章…基本上半个月都很难出一篇,但还是想把这个系列做起来,主要是为了记录自己学习和开发的过程,以便在面试的时候讲项目,能说得头头是道(◍•ᴗ•◍) 马上就要开…

Clickhouse

目录 Clickhouse简介 整体架构 数据接入层 数据存储层 数据服务层 数据应用层 Clickhouse简介 目前企业用户行为日志每天百亿量级,虽然经过数仓的分层以及数据汇总层通用维度指标的预计算,有些个性化的分析场景还是需要直接编写程序或sql查询&…

python人工智能学习需要学什么?

前言 如果要从科技领域找出最大的变化和革新,那么我们很难不说到“人工智能”这个关键词。人工智能催生了大量新技术、新企业和新业态,为个人、企业、国家乃至全球提供了新的经济增长点,上到谷歌、苹果、百度等巨头,下到各类创业…

发布-订阅模式解读

发布-订阅模式 先简单说一下发布订阅模式各个组件的定义: 发布者 Publisher : 状态改变时 , 向 消息中心 发送事件 ; 订阅者 Subscriber : 到 消息中心 订阅自己关心的事件 ; 消息中心 : 负责维护一个 消息队列 , 根据 消息类型 将 消息 转发给 对应的 订阅者 ; 下面按照该…

差错控制方法----循环冗余码计算

差错控制方法----循环冗余码计算 循环冗余码,又称为多项式码。CRC的工作方法是在发送端产生一个冗余码,附加在信息位后面一起发送到接收端,接收端收到的信息按发送端形成循环冗余码同样的算法进行校验,如果发现错误,则…

(附源码)php校园电子图像信息采集系统 毕业设计 010930

目 录 摘要 1 1 绪论 1 1.1 研究背景 1 1.2研究内容 1 1.3论文结构与章节安排 1 2 校园电子图像信息采集系统 系统分析 3 2.1 可行性分析 3 2.2 系统流程分析 3 2.2.1 数据增加流程 3 2.2.2 数据修改流程 4 2.3.3数据删除流程 4 2.3 系统功能分析 4 2.3.1 功能性分析 4 2.3.2 …

多态——C++第三大特性

目录 一、多态的概念 1、概念 二、多态的定义及实现 1、构成条件 2、虚函数 3、虚函数的重写 4、C11提供了override和final两个关键字,可以帮助用户检测是否重写 5、重载、覆盖(重写)、隐藏(重定义)的对比 三、…

pytorch环境配置

pytorch环境配置pytorch环境配置1.NVIDIA驱动安装与更新1.查看自己的电脑显卡版本2.下载显卡驱动3.安装与验证2.pytorch环境安装1.打开anaconda的终端2. 创建虚拟环境3.换源4.安装5.验证3.pycharm项目的pytorch环境设置pytorch环境配置 使用Anacondapycharm搭建pytorch环境 提…

常见的四大搜索引擎区别

一般应用或网站的信息会存储在数据库中,而随着时间的推移,数据库中的信息量达到一个量级后会出现访问速度变慢的情况,例如用户在客户端搜索一个商品名称,系统可能加载了好几秒才显示数据,这个时候就需要进行一些优化处…

ET框架(三)

Model》数据 HotFix》行为 ET框架中的ECS和Unity的ECS无关 hotfix 静态类静态方法>行为 可以控制组件 Model》数据 继承Entity IAwake初始化 Scene实体的子实体类型 特殊: Unity.hotfixView : Unity相关的行为 Unity .modeView: Unity相关的数据 代码公用&a…

WSL_01 Windows WSL 安装并配置镜像与SSH

文章目录1 WSL介绍2 安装步骤2.1 启用适用于 Linux 的 Windows 子系统2.2 检查运行 WSL 2 的要求2.3 启用虚拟机功能2.4 下载 Linux 内核更新包2.5 将 WSL 2 设置为默认版本2.6 安装所选的Linux 分发解决无法打开微软商店2.6.1 配置网络2.6.2 使用官方教程的链接2.6.3 使用命令…

Redis实战——达人探店

目录 1、发布笔记 1.1 上传图片 1.2. 发表博文功能: 2. 查看探店笔记 3. 点赞功能的实现 4. 点赞排行榜的实现 1、发布笔记 笔记类似点评网站的评价,往往是图文结合。 对应的表有两个 tb_blog:探店笔记表,包含笔记中的…

java计算机毕业设计springboot+vue高校本科学生综评系统

项目介绍 通篇文章的撰写基础是实际的应用需要,然后在架构系统之前全面复习大学所修习的相关知识以及网络提供的技术应用教程,以远程教育系统的实际应用需要出发,架构系统来改善现高校本科学生综评系统工作流程繁琐等问题。不仅如此以操作者的角度来说,该系统的架构能够对多媒…

网络流量回溯分析助力企业实现高效率运维(二)

背景 汽车配件电子图册系统是某汽车集团的重要业务系统。业务部门反映,汽车配件电子图册调用图纸时,出现访问慢现象。 某汽车总部已部署NetInside流量分析系统,使用流量分析系统提供实时和历史原始流量。本次分析重点针对汽车配件电子图册系…

在Python里使用ChatGPT

前言 近来chatGPT挺火的,也试玩了一下,确实挺有意思。这里记录一下在Python中如何去使用chatGPT。 本篇文章的实现100%基于 chatGPT,我是搬运工无疑了!!! 本片文章比较简单,下一篇基于本文章来写…

景联文科技:推动智慧医疗进程,浅谈运用到的数据标注技术

“近年来,人工智能蓬勃发展,不断赋能医疗健康领域,改善患者的就医体验,有效提高医疗质量。智能医疗的实现需要许多专业且精准的标注数据不断对智慧医疗技术中包含的算法模型进行训练调优。” 从2015年至今,我国急性脑梗…

java+MySQL 002ssm病人健康档案管理系统#毕业设计

随着时代的发展,人们对健康越来越重视。如何呢能够更好的对病人的健康档案信息进行管理是当前很多人关心的一个问题。本期系统也是出于这样的目的而进行开发的。 研究内容 1.不同用户的登录问题:根据用户的类别;超级管理员、普通用户;实现用户操作权限的区分并显示不…

三、数据链路层(四)流量控制和可靠传输机制

目录 4.1流量控制和可靠传输机制 4.2三种传统ARQ方式 4.2.1单帧滑动窗口与停止-等待协议 4.2.2多帧滑动窗口与后退N帧协议(GBN) 4.2.3多帧滑动窗口与选择重传协议(SR) 4.2.4三种ARQ协议窗口大小问题 4.2.5信道利用率、信道…

视频号怎么做呢?如何发视频号?

视频号怎么做呢?如何发视频号? 视频号怎么做呢?如何发视频号? 1、明确方向 首先明确自己要做什么类型的账号,下面是常见的一些账号属性: 商品带货号美食号知识号影视号游戏号书单号音乐号家庭生活号医疗号…