[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 官方文檔
希望本教程對您有幫助,請點贊??收藏?關注支持!歡迎在評論區留言交流技術細節!