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>     

📌 各依赖说明如下:

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


原始标题:Spring Boot Ehcache Example