1. 概述
本文通过一个简单的例子展示如何在 Spring Boot 中集成并使用 Ehcache 3。Ehcache 3 是 JSR-107(Java 缓存 API)规范的一个实现,提供了标准的缓存管理能力。
我们的示例是一个 RESTful 接口服务,用于计算一个数字的平方值,并返回 JSON 格式的结果。
2. 依赖配置
首先,我们需要引入以下 Maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.10.8</version>
<classifier>jakarta</classifier>
</dependency>
📌 各依赖说明如下:
- spring-boot-starter-web:用于构建 Web 应用。
- spring-boot-starter-cache:提供 Spring 缓存抽象支持。
- javax.cache:cache-api:JSR-107 标准缓存接口。
- org.ehcache:ehcache:Ehcache 3 的核心实现。
3. 示例代码
3.1 控制器
我们先创建一个简单的 REST 控制器,它调用服务类计算平方值并返回 JSON 字符串:
@RestController
@RequestMapping("/number", produces = MediaType.APPLICATION_JSON_VALUE)
public class NumberController {
@Autowired
private NumberService numberService;
@GetMapping("/square/{number}")
public String getSquare(@PathVariable Long number) {
log.info("call numberService to square {}", number);
return String.format("{\"square\": %s}", numberService.square(number));
}
}
⚠️ 注意:Spring Boot 3 中默认使用的是 MediaType.APPLICATION_JSON
,不再推荐使用 APPLICATION_JSON_UTF8_VALUE
。
3.2 服务层
在服务类中,我们使用 @Cacheable
注解来启用缓存功能:
@Service
public class NumberService {
@Cacheable(value = "squareCache", key = "#number", condition = "#number > 10")
public BigDecimal square(Long number) {
BigDecimal square = BigDecimal.valueOf(number)
.multiply(BigDecimal.valueOf(number));
log.info("square of {} is {}", number, square);
return square;
}
}
✅ 这段代码的含义是:
- 使用名为
squareCache
的缓存。 - 以传入参数
number
作为缓存键。 - 当
number > 10
时才进行缓存。
💡 Spring 会为这个类生成代理对象,在方法执行前检查缓存中是否存在结果,如果命中则直接返回,否则执行方法并将结果缓存起来。
3.3 主程序入口
最后是 Spring Boot 的启动类:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4. 缓存配置
4.1 启用缓存支持
要在 Spring 中启用基于注解的缓存功能,需要添加 @EnableCaching
注解:
@Configuration
@EnableCaching
public class CacheConfig {
}
4.2 配置 Ehcache XML 文件
Spring Boot 不会自动加载默认的 ehcache.xml
,我们需要手动指定配置文件路径:
spring.cache.jcache.config=classpath:ehcache.xml
然后我们创建 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"
xsi:schemaLocation="
http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
<cache alias="squareCache">
<key-type>java.lang.Long</key-type>
<value-type>java.math.BigDecimal</value-type>
<expiry>
<ttl unit="seconds">30</ttl>
</expiry>
<listeners>
<listener>
<class>com.baeldung.cachetest.config.CacheEventLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">2</heap>
<offheap unit="MB">10</offheap>
</resources>
</cache>
</config>
📌 配置要点:
alias="squareCache"
对应 Java 代码中的缓存名称。ttl unit="seconds">30
表示缓存项 30 秒后过期。<heap>
和<offheap>
定义了内存和堆外存储资源。- 添加了一个监听器
CacheEventLogger
来记录缓存事件。
4.3 缓存事件监听器
public class CacheEventLogger implements CacheEventListener<Object, Object> {
@Override
public void onEvent(CacheEvent<?, ?> cacheEvent) {
log.info("Cache event {} for item with key {}. Old value = {}, New value = {}",
cacheEvent.getType(), cacheEvent.getKey(),
cacheEvent.getOldValue(), cacheEvent.getNewValue());
}
}
5. 实战演示
5.1 启动项目
使用 Maven 启动应用:
mvn spring-boot:run
5.2 第一次访问
访问地址:http://localhost:8080/number/square/12
返回结果:
{"square": 144}
日志输出:
INFO [nio-8080-exec-1] c.b.cachetest.rest.NumberController : call numberService to square 12
INFO [nio-8080-exec-1] c.b.cachetest.service.NumberService : square of 12 is 144
INFO [e [_default_]-0] c.b.cachetest.config.CacheEventLogger : Cache event CREATED for item with key 12. Old value = null, New value = 144
可以看到服务方法被执行,并且缓存被创建。
5.3 再次访问相同 URL
刷新浏览器,日志变为:
INFO [nio-8080-exec-2] c.b.cachetest.rest.NumberController : call numberService to square 12
此时 NumberService.square()
方法未再执行,说明缓存已生效。
5.4 缓存过期后再次访问
等待 30 秒后刷新页面,会看到如下日志:
INFO [nio-8080-exec-1] (...) NumberController : call numberService to square 12
INFO [e [_default_]-1] (...) CacheEventLogger : Cache event EXPIRED for item with key 12. Old value = 144,New value = null
INFO [nio-8080-exec-1] (... )NumberService : square of 12 is 144
INFO [e [_default_]-1] (...) CacheEventLogger : Cache event CREATED for item with key 12. Old value = null, New value = 144
说明缓存已过期并重新生成。
5.5 条件缓存测试
访问地址:http://localhost:8080/number/square/3
返回结果:
{"square": 9}
但是没有触发缓存逻辑,因为我们在 @Cacheable
上设置了条件:condition = "#number > 10"
。
6. 小结
这篇文章简单粗暴地带你走了一遍 Spring Boot + Ehcache 的整合流程,涵盖了从依赖引入、注解使用到 XML 配置的完整流程。
📌 要点回顾:
- 使用
@Cacheable
可以轻松接入缓存机制。 - Ehcache 3 支持丰富的配置选项,包括 TTL、内存策略等。
- 缓存事件监听器可用于调试或监控目的。
- 条件缓存可以避免不必要的缓存开销。
✅ 项目源码可以在 GitHub 上找到:https://github.com/eugenp/tutorials/tree/master/spring-boot-modules/spring-boot-caching