[Java实战]Spring Boot 3 整合 Ehcache 3(十九)
[Java实战]Spring Boot 3 整合 Ehcache 3(十九)
引言
在微服务和高并发场景下,缓存是提升系统性能的关键技术之一。Ehcache 作为 Java 生态中成熟的内存缓存框架,其 3.x 版本在性能、功能和易用性上均有显著提升。本文将详细介绍如何在 Spring Boot 3 中整合 Ehcache 3,并实现高效缓存管理。
一. 环境准备
- open JDK 17+:Spring Boot 3 要求 Java 17 及以上。
- Spring Boot 3.4.5:使用最新稳定版。
- Ehcache 3.10+:支持 JSR-107 标准,兼容 Spring Cache 抽象。
- 构建工具:Maven 或 Gradle(本文以 Maven 为例)。
二. 添加依赖
在 pom.xml
中添加 Ehcache 3 和 Spring Cache 依赖:
<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Cache 抽象 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><!-- Ehcache 3.x 核心库 --><dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.10.0</version><classifier>jakarta</classifier> <!-- 针对高版本 JDK,添加 Jakarta 分类器 --></dependency>
三. 配置 Ehcache 3
3.1 启用缓存
在 Spring Boot 主类或配置类上添加 @EnableCaching
注解:
@SpringBootApplication
@EnableCaching
@MapperScan("com.example.springboot3.mapper")
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
3.2 创建 Ehcache 配置文件
在 resources
目录下新建 ehcache.xml
,定义缓存策略:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.ehcache.org/v3"xmlns:jsr107="http://www.ehcache.org/v3/jsr107"><service><jsr107:defaults enable-management="true" enable-statistics="true"/></service><cache alias="productCache"><key-type>java.lang.String</key-type><value-type>java.lang.Object</value-type><expiry><ttl unit="seconds">120</ttl></expiry><resources><heap unit="entries">1000</heap><offheap unit="MB">10</offheap></resources></cache>
</config>
3.3 配置 Spring Boot 使用 Ehcache
在 application.yml
中指定 Ehcache 配置文件路径:
spring:cache:jcache:config: classpath:ehcache.xmltype: jcache
四. 实现缓存逻辑
4.1 定义服务类
使用 @Cacheable
、@CachePut
和 @CacheEvict
注解管理缓存:
/*** ProductService - 类功能描述** @author csdn:曼岛_* @version 1.0* @date 2025/5/12 15:01* @since JDK 17*/
@Service
public class ProductService {@Autowiredprivate ProductMapper productMapper;//从数据库查询并缓存结果@Cacheable(cacheNames = "productCache",key = "#id.toString()")public Product getProductById(Long id) {return productMapper.selectById(id);}//更新产品信息并更新缓存@CachePut(cacheNames = "productCache",key = "#product.id.toString()")public void updateProduct(Product product) {productMapper.updateById(product);}//更新或删除时清除缓存@CacheEvict(cacheNames = "productCache", key = "#id.toString()", allEntries = false)public void deleteProduct(Long id) {productMapper.deleteById(id);}
}
五. 高级配置与优化
5.1 自定义 CacheManager
通过 JCacheManagerCustomizer
配置多级缓存或动态缓存:
/*** EhcacheConfig - 类功能描述** @author csdn:曼岛_* @version 1.0* @date 2025/5/13 14:21* @since JDK 17*/
@Configuration
public class EhcacheConfig {@Beanpublic JCacheManagerCustomizer cacheManagerCustomizer() {return cm -> {CachingProvider provider = Caching.getCachingProvider();CacheManager cacheManager = null;try {cacheManager = provider.getCacheManager(getClass().getResource("/ehcache.xml").toURI(),getClass().getClassLoader());} catch (URISyntaxException e) {e.printStackTrace();}};}
}
5.2 监控与统计
启用 Ehcache 统计信息:
spring:cache:jcache:provider: org.ehcache.jsr107.EhcacheCachingProvider
在代码中获取统计信息:
Cache<Long, Product> cache = cacheManager.getCache("productCache", Long.class, Product.class);
Eh107Cache<Long, Product> eh107Cache = (Eh107Cache<Long, Product>) cache;
Ehcache<Long, Product> ehcache = eh107Cache.getEhcache();
Statistics statistics = ehcache.getRuntimeConfiguration().getStatistics();
六. 测试验证
6.1 编写单元测试
使用 @SpringBootTest
测试缓存行为:
@SpringBootTest
public class ProductServiceTest {@Autowiredprivate ProductService productService;@Autowiredprivate ProductMapper productMapper;@Autowiredprivate CacheManager cacheManager;@Testpublic void testGetProductById() {// 清空缓存Cache cache = cacheManager.getCache("productCache");cache.clear();// 创建一个测试产品Product product = new Product();product.setName("Product");product.setPrice(100);product.setStock(1);productMapper.insert(product);// 第一次调用,应该从数据库获取数据Product result1 = productService.getProductById(product.getId());assertNotNull(result1);assertEquals(product.getName(), result1.getName());// 第二次调用,应该从缓存获取数据Product result2 = productService.getProductById(product.getId());assertNotNull(result2);assertEquals(product.getName(), result2.getName());// 验证缓存中存在该数据Cache.ValueWrapper valueWrapper = cache.get(product.getId().toString());assertNotNull(valueWrapper);assertEquals(product.getName(), ((Product) valueWrapper.get()).getName());// 打印缓存结果System.out.println("Cached Product: " + valueWrapper.get());}@Testpublic void testUpdateProduct() {// 清空缓存Cache cache = cacheManager.getCache("productCache");cache.clear();// 创建一个测试产品Product product = new Product();product.setName("Product");product.setPrice(100);product.setStock(2);productMapper.insert(product);// 更新产品信息product.setName("Updated Product");product.setPrice(200);productService.updateProduct(product);// 验证数据库中的数据是否更新Product updatedProduct = productMapper.selectById(product.getId().toString());assertEquals("Updated Product", updatedProduct.getName());assertEquals(200, updatedProduct.getPrice());// 验证缓存中的数据是否更新Cache.ValueWrapper valueWrapper = cache.get(product.getId().toString());assertNotNull(valueWrapper);assertEquals("Updated Product", ((Product) valueWrapper.get()).getName());}@Testpublic void testDeleteProduct() {// 清空缓存Cache cache = cacheManager.getCache("productCache");cache.clear();// 创建一个测试产品Product product = new Product();product.setName("Test Product");product.setPrice(100);product.setStock(1);productMapper.insert(product);// 将产品信息放入缓存productService.getProductById(product.getId());// 删除产品productService.deleteProduct(product.getId());// 验证数据库中的数据是否删除assertNull(productMapper.selectById(product.getId()));// 验证缓存中的数据是否删除assertNull(cache.get(product.getId().toString()));}
}
接口测试:
6.2 查看缓存状态
通过 Actuator 或日志观察缓存命中率(需添加 Actuator 依赖):
management:endpoints:web:exposure:include: cache
七. 常见问题与解决方案
7.1 缓存不生效
- 检查点:确保
@EnableCaching
已启用,方法为public
,且调用来自 Spring 代理对象。 - 日志调试:设置
logging.level.org.springframework.cache=DEBUG
。
7.2 序列化异常
- 原因:缓存对象未实现
Serializable
。 - 解决:为缓存对象添加
implements Serializable
或配置序列化策略。
7.3 依赖冲突
- 排查工具:使用
mvn dependency:tree
检查版本一致性。 - 推荐:使用 Spring Boot 管理的 Ehcache 版本。
八. 性能对比与选型建议
- Ehcache vs Caffeine:Ehcache 支持多级缓存和持久化,适合复杂场景;Caffeine 更轻量,适合纯内存缓存。
- Ehcache vs Redis:Ehcache 适用于单机内存缓存,Redis 适合分布式缓存。
结语
通过本文,您已掌握在 Spring Boot 3 中整合 Ehcache 3 的核心步骤与优化技巧。合理利用缓存机制,可以显著提升系统性能。建议根据业务场景选择合适的缓存策略,并通过监控持续优化。
扩展阅读:Ehcache 官方文档
希望本教程对您有帮助,请点赞❤️收藏⭐关注支持!欢迎在评论区留言交流技术细节!
相关文章:

[Java实战]Spring Boot 3 整合 Ehcache 3(十九)
[Java实战]Spring Boot 3 整合 Ehcache 3(十九) 引言 在微服务和高并发场景下,缓存是提升系统性能的关键技术之一。Ehcache 作为 Java 生态中成熟的内存缓存框架,其 3.x 版本在性能、功能和易用性上均有显著提升。本文将详细介绍…...

建筑物渗水漏水痕迹发霉潮湿分割数据集labelme格式1357张1类别
数据集中有增强图片详情看图片 数据集格式:labelme格式(不包含mask文件,仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数):1357 标注数量(json文件个数):1357 标注类别数:1 标注类别名称:["water&qu…...
Doris和Clickhouse对比
目录 一、Doris和Clickhouse对比1. 底层架构**DorisClickHouse** 2. 运行原理DorisClickHouse 3. 使用场景DorisClickHouse 4. 优缺点对比总结 二、MPP架构和Shared-Nothing 架构对比1. 什么是 MPP 架构?定义特点典型代表 2. 什么是 Shared-Nothing 架构?…...

第二十二天打卡
数据预处理 import pandas as pd from sklearn.model_selection import train_test_splitdef data_preprocessing(file_path):"""泰坦尼克号生存预测数据预处理函数参数:file_path: 原始数据文件路径返回:preprocessed_data: 预处理后的数据集""&quo…...
Android Activity之间跳转的原理
一、Activity跳转核心流程 Android Activity跳转的底层实现涉及 系统服务交互、进程间通信(IPC) 和 生命周期管理,主要流程如下: startActivity() 触发请求 应用调用 startActivity() 时,通过 Inst…...
MATLAB 矩阵与数组操作基础教程
文章目录 前言环境配置一、创建矩阵与数组(一)直接输入法(二)特殊矩阵生成函数(三)使用冒号表达式创建数组 二、矩阵与数组的基本操作(一)访问元素(二)修改元…...
【Linux】第十六章 分析和存储日志
1. RHEL 日志文件保存在哪个目录中? 一般存储在 /var/log 目录中。 2. 什么是syslog消息和非syslog消息? syslog消息是一种标准的日志记录协议和格式,用于系统和应用程序记录日志信息。它规定了日志消息的结构和内容,包括消息的…...

解锁性能密码:Linux 环境下 Oracle 大页配置全攻略
在 Oracle 数据库运行过程中,内存管理是影响其性能的关键因素之一。大页内存(Large Pages)作为一种优化内存使用的技术,能够显著提升 Oracle 数据库的运行效率。本文将深入介绍大页内存的相关概念,并详细阐述 Oracle 在…...

Spark,在shell中运行RDD程序
在hdfs中/wcinput中创建一个文件:word2.txt在里面写几个单词 启动hdfs集群 [roothadoop100 ~]# myhadoop start [roothadoop100 ~]# cd /opt/module/spark-yarn/bin [roothadoop100 ~]# ./spark-shell 写个11测试一下 按住ctrlD退出 进入环境:spa…...

SAP学习笔记 - 开发11 - RAP(RESTful Application Programming)简介
上一章学习了BTP架构图,实操创建Directory/Subaccount,BTP的内部组成,BTP Cockpit。 SAP学习笔记 - 开发10 - BTP架构图,实操创建Directory/Subaccount,BTP的内部组成,BTP Cockpit-CSDN博客 本章继续学习S…...

数据防泄密安全:企业稳健发展的守护盾
在数字化时代,数据已成为企业最核心的资产之一。无论是客户信息、财务数据,还是商业机密,一旦泄露,都可能给企业带来不可估量的损失。近年来,数据泄露事件频发,如Facebook用户数据泄露、Equifax信用数据外泄…...

MySQL之基础索引
目录 引言 1、创建索引 2、索引的原理 2、索引的类型 3、索引的使用 1.添加索引 2.删除索引 3.删除主键索引 4.修改索引 5.查询索引 引言 当一个数据库里面的数据特别多,比如800万,光是创建插入数据就要十几分钟,我们查询一条信息也…...
Openshift节点Disk pressure
OpenShift 监控以下指标,并定义以下垃圾回收的驱逐阈值。请参阅产品文档以更改任何驱逐值。 nodefs.available 从 cadvisor 来看,该node.stats.fs.available指标表示节点文件系统(所在位置)上有多少可用(剩余…...

拉丁方分析
本文是实验设计与分析(第6版,Montgomery著傅珏生译)第4章随机化区组,拉丁方,以及有关的设计第4.2节的python解决方案。本文尽量避免重复书中的理论,着于提供python解决方案,并与原书的运算结果进行对比。您…...
Pomelo知识框架
一、Pomelo 基础概念 Pomelo 简介 定位:分布式游戏服务器框架(网易开源)。 特点:高并发、可扩展、多进程架构、支持多种通信协议(WebSocket、TCP等)。 适用场景:MMO RPG、实时对战、社交游戏等…...

软考软件设计师中级——软件工程笔记
1.软件过程 1.1能力成熟度模型(CMM) 软件能力成熟度模型(CMM)将软件过程改进分为以下五个成熟度级别,每个级别都定义了特定的过程特征和目标: 初始级 (Initial): 软件开发过程杂乱无章…...
基于事件驱动和策略模式的差异化处理方案
一、支付成功后事件驱动 1、支付成功事件 /*** 支付成功事件** author ronshi* date 2025/5/12 14:40*/ Getter Setter public class PaymentSuccessEvent extends ApplicationEvent {private static final long serialVersionUID 1L;private ProductOrderDO productOrderDO;…...

5.5.1 WPF中的动画2-基于路径的动画
何为动画?一般只会动。但所谓会动,还不仅包括位置移动,还包括角度旋转,颜色变化,透明度增减。动画本质上是一个时间段内某个属性值(位置、颜色等)的变化。因为属性有很多数据类型,它们变化也需要多种动画类比如: BooleanAnimationBase\ ByteAnimationBase\DoubleAnima…...
计算机网络:手机和基站之间的通信原理是什么?
手机与基站之间的通信是无线通信技术的核心应用之一,涉及复杂的物理层传输、协议交互和网络管理机制。以下从技术原理、通信流程和关键技术三个层面深入解析这一过程: 一、蜂窝网络基础架构 1. 蜂窝结构设计 基本原理:将服务区域划分为多个六边形“蜂窝小区”,每个小区由*…...
PostgreSQL常用DML操作的锁类型归纳
DML锁类型分析 本文对PostgreSQL的insert、 update、 truncate、 delete等常用DML操作的锁类型进行了归纳类比: 包括是否排他、 共享、 表级、 行级等的总结。 truncate :access exclusive mode(block all read/write)、table-le…...
Apache Flink 与 Flink CDC:概念、联系、区别及版本演进解析
Apache Flink 与 Flink CDC:概念、联系、区别及版本演进解析 在实时数据处理和流式计算领域,Apache Flink 已成为行业标杆。而 Flink CDC(Change Data Capture) 作为其生态中的重要组件,为数据库的实时变更捕获提供了强大的能力。 本文将从以下几个方面进行深入讲解: 什…...
数学复习笔记 8
前言 成为一个没有感情的刷题机器就可以变得很强了。 逆矩阵的运算 随便算一下就算出来了,没啥难的。主要是用天然可交换的矩阵来算。有三个天然可交换的矩阵,某矩阵和单位阵,该矩阵和它的伴随矩阵,该矩阵和它的逆矩阵。一定要…...
FunASR:语音识别与合成一体化,企业级开发实战详解
简介 FunASR是由阿里巴巴达摩院开源的高性能语音识别工具包,它不仅提供语音识别(ASR)功能,还集成了语音端点检测(VAD)、标点恢复、说话人分离等工业级模块,形成了完整的语音处理解决方案。 FunASR支持离线和实时两种模式,能够高效处理多语言音频,并提供高精度的识别结果。…...
rust-candle学习笔记11-实现一个简单的自注意力
参考:about-pytorch 定义ScaledDotProductAttention结构体: use candle_core::{Result, Device, Tensor}; use candle_nn::{Linear, Module, linear_no_bias, VarMap, VarBuilder, ops};struct ScaledDotProductAttention {wq: Linear,wk: Linear,wv: …...
读入csv文件写入MySQL
### 使用 Spark RDD 读取 CSV 文件并写入 MySQL 的实现方法 #### 1. 环境准备 在使用 Spark 读取 CSV 文件并写入 MySQL 数据库之前,需要确保以下环境已配置完成: - 添加 Maven 依赖项以支持 JDBC 连接。 - 配置 MySQL 数据库连接参数,包括 …...

Andorid之TabLayout+ViewPager
文章目录 前言一、效果图二、使用步骤1.主xml布局2.activity代码3.MyTaskFragment代码4.MyTaskFragment的xml布局5.Adapter代码6.item布局 总结 前言 TabLayoutViewPager功能需求已经是常见功能了,我就不多解释了,需要的自取。 一、效果图 二、使用步骤…...
C++GO语言微服务之用户信息处理②
目录 01 03-获取用户信息-上 02 04-获取用户信息-下 03 05-更新用户名实现 01 06-中间件简介和中间件类型 02 07-中间件测试和模型分析 03 08-中间件测试案例和小结 04 09-项目使用中间件 01 03-获取用户信息-上 ## Cookie操作 ### 设置Cookie go func (c *Context) …...

26考研——中央处理器_指令流水线_流水线的冒险与处理 流水线的性能指标 高级流水线技术(5)
408答疑 文章目录 六、指令流水线流水线的冒险与处理结构冒险数据冒险延迟执行相关指令采用转发(旁路)技术load-use 数据冒险的处理 控制冒险 流水线的性能指标流水线的吞吐率流水线的加速比 高级流水线技术超标量流水线技术超长指令字技术超流水线技术 …...
Java 与 Go 语言对比
Java 和 Go (Golang) 是两种流行的编程语言,各有其设计哲学和应用场景。以下是它们的详细对比: 1. 基本特性 特性JavaGo诞生时间1995 (Sun Microsystems)2009 (Google)设计目标“Write Once, Run Anywhere”简洁、高效的系统编程语言语言类型面向对象多…...
OpenUCX 库介绍与使用指南
OpenUCX 库介绍与使用指南 OpenUCX 简介 OpenUCX (Unified Communication X) 是一个高性能、开源通信框架,专为大规模分布式计算和加速计算设计。它提供了统一的API,支持多种网络硬件和协议,包括InfiniBand、RoCE、TCP等。 主要特点 高性…...