WireMock 中请求头匹配与响应配置的一些实践
记录用 WireMock 挡服务时,通过 JSON 映射文件和 Java API 做请求头匹配、响应头与响应体配置的两种方式及细节。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-08-04 01:15:37 Java 本地缓存 Caffeine Guava Cache Ehcache
这四个方案我都在不同项目里用过,有的是从线上事故之后换上去的,有的是遗留代码里一直跑着也懒得动。先说结论再展开就没意思了,还是顺着记忆捋一遍吧。
HashMap是那种你刚写完逻辑、还没想好缓存怎么搞时随手塞进去的东西。一个 Map<String, Object> 顶着,存取都是O(1),零依赖。测试环境跑完全没问题,甚至一些小工具里现在还在用。坑在哪里呢?没淘汰策略,内存往上蹿你根本控制不住。而且它不是线程安全的,得自己包一层 ConcurrentHashMap 或者加锁。
没有过期时间,没有加载回调,什么都没有。这就是个裸的KV容器,说它是缓存方案其实有点抬举它了。如果你只是放几个配置项,生命周期跟JVM一样长,那没问题。线上正经服务里别直接用,血的教训。
后来有一阵大家开始用Guava Cache。谷歌出的,比HashMap多了很多工程化的东西。
最大容量、基于写入或访问的过期时间、异步加载,这些都有了。可以配合 CacheLoader,取不到key的时候自动回源查数据库,不用自己写模板代码。统计功能也挺好用,命中率、加载耗时都能拿到,排查问题省事。那时候感觉基本够用了。但它用的是LRU淘汰算法,在高并发写入的场景下,性能会下来一点。另外内存占用不算省,跟后来的Caffeine比差出一截——测试里能多出将近50%。如果你的项目是遗留系统,已经引了Guava,也没有极端性能要求,继续用着不折腾完全合理。
接着就是Caffeine。这个库的作者就是原来维护Guava Cache的那位,相当于把之前觉得没做好的地方重新搞了一遍。算法换成了W-TinyLFU,近似最优的命中率,读写速度非常快。Spring Boot 2.x开始直接把它作为默认缓存实现,依赖都不用自己加了,自动配置开箱即用。内存友好很多,比Guava Cache能省差不多一半。支持异步加载、批量操作、单个key设置过期时间,跟Guava比基本是全方位升级。
现在我但凡新起一个服务,只要涉及本地缓存,顺手就上Caffeine,没什么犹豫的。除非真的在意那个额外依赖——但Spring Boot已经替你引了。
Ehcache是另一种路线。它不光是在堆内存里存东西,还可以堆外内存、磁盘、甚至搞集群同步。Hibernate的二级缓存默认实现就是它,所以很多老项目里都会看到。
三级存储一起上的时候,缓存容量可以做得很大,重启也不会全丢,堆外和磁盘里的数据能恢复回来。支持JSR107标准,用Spring Cache抽象接进去也挺顺。缺点也很明显:纯内存场景下性能比Caffeine差一截,而且配置项多,磁盘缓存如果没限制好空间,会把盘写满。所以它不是用来抢那点纳秒级延迟的,是解决容量和持久化问题的。如果你的缓存数据量很大,或者需要跨节点同步,Ehcache才有用武之地。
技术选型没有银弹,但可以理几条实在的思路:
如果追求性能,服务延迟敏感,而且已经是Spring Boot 2.x以上,直接用Caffeine就行。多数情况连自定义配置都不用加,默认就很好。
如果系统里已经用着Guava Cache,又不是瓶颈,不要为了换而换。但新写代码就别再选它了,除非引不了新依赖。
Ehcache用在需要大容量或者持久化缓存的场景,比如缓存了一堆查询结果希望重启不丢,或者要给Hibernate做二级缓存。堆外内存和磁盘那两级,别一上来就开,先评估数据量再说。
HashMap嘛,写个demo或者内嵌工具随便用,别让它出现在生产环境的代码评审里。
我自己现在的默认选择是Caffeine。小项目直接上,大项目稍微调一下容量和过期策略就行,基本不用折腾。
当初从Guava迁过来的时候,内存占用降了一截,毛刺也少了,线上平稳得多。
上面这些主要是本地缓存,不涉及Redis那种集中式缓存,那个是另一个维度的问题了。先把本地的搞定,该上分布式的时候再上,别混在一起选。
记录用 WireMock 挡服务时,通过 JSON 映射文件和 Java API 做请求头匹配、响应头与响应体配置的两种方式及细节。
记录使用 MinIO Java SDK 生成预签名 URL 的实践,包含下载和上传场景,以及一些容易出错的点。
记录在 Aspose.PDF 里加载本地 TTF 字体,以及绕过 TTC 格式不支持问题的两种可行方案。
记录 datetime 字段定义、插入、格式化查询以及 Java 端类型映射、时区等问题,避免线上踩坑。
拥抱Java 8及更高版本带来的日期处理革新!本文聚焦于yyyy-MM-dd格式化,详细对比传统SimpleDateFormat与现代DateTimeFormatter。深入探讨DateTimeFormatter为何成为未来主流,其不可变性、线程安全等核心优势如何助你构建更健壮、高效的应用。是时候升级你的日期格式化方式了!