还不会在 SpringBoot 中设置 HTTP 缓存?来造个轮子~
Posted Java知音_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了还不会在 SpringBoot 中设置 HTTP 缓存?来造个轮子~相关的知识,希望对你有一定的参考价值。
点击关注公众号,实用技术文章及时了解
Spring Boot 控制 HTTP缓存
HTTP协议的缓存策略可以缩短网页请求资源的距离,减少延迟,节省网络流量,并且由于缓存文件可以重复利用,降低网络负荷,加快客户端响应。
如何利用 HTTP缓存 进行一些骚操作呐,是我最近思考的问题。查看了Spring Boot对HTTP缓存的支持也只有org.springframework.web.filter.ShallowEtagHeaderFilter
和plus.wcj.heifer.boot.HeiferBootAutoConfiguration#addResourceHandlers
这个两个方式能对HTTP缓存进行骚操作,
org.springframework.web.filter.ShallowEtagHeaderFilter
只支持静态资源的缓存协商,看了一下注释说明只节省带宽,而不是服务器性能。plus.wcj.heifer.boot.HeiferBootAutoConfiguration#addResourceHandlers
可以支持HTTP API
,但是不支持RESTful API
。
去GitHub寻找一下有没有支持HTTP缓存的轮子,一顿寻找下来颗粒无收,那索性就自己造轮子吧。
缓存协商机制
维护缓存过期网上有很多的文章,这里就不再赘述了,下面列出一些文章
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
https://web.dev/i18n/en/http-cache/
因为HTTP协议的版本问题,就采用了HTTP协议1.0的实现了。
request
If-None-Match
response
Cache-control
ETag
就用以上三个headers来实现缓存协商机制,Cache-control
用于控制缓存过期时间,If-None-Match
和ETag
用于缓存协商,基于上面3个标签我们来实现HTTP缓存和缓存协商吧。
轮子使用
吭哧吭哧2天,轮子已经造好了并且已经发布到maven中央仓库了,这里就略过实现过程了,感兴趣的可以去看一下源码。
githu地址:
https://github.com/galaxy-sea/libby-http-cache-control
maven中央库:
https://repo1.maven.org/maven2/plus/wcj/libby-http-cache-control/2022.1.0/
maven引入,
<dependency>
<groupId>plus.wcj</groupId>
<artifactId>libby-http-cache-control</artifactId>
<version>2022.1.0</version>
</dependency>
一个简单的小DEMO, 访问
/html
就会出现一个简单的网页了,然后大家就点击上面的button开始测试吧,
@RestController
@RequestMapping
public class CacheController
private Map<String, Long> data = new HashMap<>();
@GetMapping("cache/id")
@HttpCacheControl(key = "#id",value = "max-age=10, public")
public Long get(@PathVariable String id)
return data.computeIfAbsent(id, s -> System.currentTimeMillis());
@PostMapping("cache/id")
@HttpETagBind(key = "#id")
public void post(@PathVariable String id)
data.put(id, System.currentTimeMillis());
@GetMapping("html")
public ResponseEntity<String> html()
return ResponseEntity
.ok()
.body("<!DOCTYPE html><html><head><meta charset=\\"utf-8\\"><script src=\\"https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js\\"></script><script>$(document).ready(function()$(\\"button:nth-child(1)\\").click(function()$.get(\\"./cache/1\\",function(data,status)$(\\"ol\\").append(\\"<li>cache1: data: \\"+data+\\"</li>\\")));$(\\"button:nth-child(2)\\").click(function()$.get(\\"./cache/2\\",function(data,status)$(\\"ol\\").append(\\"<li>cache2: data: \\"+data+\\"</li>\\")));$(\\"button:nth-child(3)\\").click(function()$.post(\\"./cache/1\\",function(data,status)$(\\"ol\\").append(\\"<li>cache1: modify cache1</li>\\")));$(\\"button:nth-child(4)\\").click(function()$.post(\\"./cache/2\\",function(data,status)$(\\"ol\\").append(\\"<li>cache2: modify cache2</li>\\"))));</script></head><body><button>get cache1</button><button>get cache2</button><button>modify cache1</button><button>modify cache2</button><ol><li>start test</li></ol></body></html>");
缓存问题
因为HTTP协议只是一个规范,所以不同的客户端
和代理服务
对HTTP实现各不相同,不同的客户端+代理服务的组合会出现不同的缓存效果。
浏览器缓存 问题
测试的时候建议使用多个浏览器进行测试,对于没有实现 HTTP缓存标准
的发包工具,是不会去维护Cache-control
、If-None-Match
、ETag
等缓存标签。
如果你的 API设计风格 RESTful风格,浏览器(Chrome、firefox)会帮你维护If-None-Match
标签。
GET cache/id
POST cache/id
GET cache/id
浏览器会在步骤2删除本地缓存,那么步骤3的If-None-Match
就不会传输了。
总结 Chrome、firefox对HTTP缓存的实现是最标准的,API发包工具不维护HTTP缓存,
代理缓存 问题
在进行缓存测试的发现一个nginx、Apache APISIX、Spring Cloud Gateway等等网关的一些小问题。
CacheControl: max-age=10, public
,从理论上来说public
应该让代理服务
把数据缓存在本地(有些网关需要增加配置才能开启 代理缓存
),但是不同的网关对HTTP缓存实现的不同,会表现不同的行为。
如果使用了(共享)代理缓存
请配合 运维兄弟 多多测试。
如果使用了(共享)代理缓存
请配合 运维兄弟 多多测试。
如果使用了(共享)代理缓存
请配合 运维兄弟 多多测试。
推荐
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!
以上是关于还不会在 SpringBoot 中设置 HTTP 缓存?来造个轮子~的主要内容,如果未能解决你的问题,请参考以下文章
Springboot应用中设置Cookie的SameSite属性
如何在 springboot graphql 应用程序中设置基本 url
SpringBoot——SpringBoot中设置字符集编码的两种方式