1. 概述
讓我們以使用 Ehcache 與 Spring Boot 的示例為例。我們將使用 Ehcache 版本 3,因為它實現了 JSR-107 緩存管理器。
該示例是一個簡單的 REST 服務,它計算數字的平方。
2. 依賴關係
This section describes the dependencies required to run this application.
2.1. Required Libraries
- React: 16.8.6
- Node.js: 12.x
- npm: 6.x
- Webpack: 4.28.3
2.2. Development Dependencies
- Babel: 7.8.3
- Jest: 26.6.3
- Cypress: 4.8.0
2.3. Third-Party Libraries
- Axios: 0.21.1 (用於 HTTP 請求)
- Lodash: 4.17.20 (提供實用工具函數)
<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>
<ul>
<li><a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web"><em>spring-boot-starter-web</em></a></li>
<li><em><a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache">spring-boot-starter-cache</a></em></li>
<li><a href="https://mvnrepository.com/artifact/javax.cache/cache-api"><em>javax.cache:cache-api</em></a></li>
<li><a href="https://mvnrepository.com/artifact/org.ehcache/ehcache"><em>org.ehcache:ehcache</em></a></li>
</ul>
3. 示例
讓我們創建一個簡單的 REST 控制器,該控制器調用一個服務來計算數字的平方,並將結果作為 JSON 字符串返回:
@RestController
@RequestMapping("/number", MediaType.APPLICATION_JSON_UTF8_VALUE)
public class NumberController {
// ...
@Autowired
private NumberService numberService;
@GetMapping(path = "/square/{number}")
public String getSquare(@PathVariable Long number) {
log.info("call numberService to square {}", number);
return String.format("{\"square\": %s}", numberService.square(number));
}
}現在我們來創建服務。
我們使用 @Cacheable 註解來標註方法,以便 Spring 處理緩存。 由於此註解,Spring 會創建一個代理來攔截對 NumberService 中 square 方法的調用,並調用 Ehcache。
我們需要提供緩存名稱以及可選的鍵。 還可以添加條件以限制緩存的內容:
@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;
}
}最後,讓我們創建我們的主要 Spring Boot 應用程序:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}4. 緩存配置
我們需要在 Spring Bean 上添加 Spring 的 <em/>@EnableCaching</em/> 註解,以便啓用 Spring 的基於註解的緩存管理。
讓我們創建一個 <em/>CacheConfig</em/> 類:
@Configuration
@EnableCaching
public class CacheConfig {
}Spring 的自動配置會發現 Ehcache 對 JSR-107 的實現。但是,默認情況下不會創建任何緩存。
因為 Spring 也未 Ehcache 都不會查找默認的 ehcache.xml 文件。我們添加以下屬性來告訴 Spring 緩存文件的位置:
spring.cache.jcache.config=classpath:ehcache.xml
讓我們創建一個名為 ehcache.xml 的文件,其中包含一個名為 squareCache 的緩存:
<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>讓我們也添加緩存事件監聽器,它會記錄 CREATED 和 EXPIRED 緩存事件:
public class CacheEventLogger
implements CacheEventListener<Object, Object> {
// ...
@Override
public void onEvent(
CacheEvent<? extends Object, ? extends Object> cacheEvent) {
log.info(/* message */,
cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
}
}5. 實際應用
我們可以使用 Maven 通過運行 mvn spring-boot:run 命令來啓動該應用程序。
然後,打開瀏覽器並訪問 8080 端口上的 REST 服務。
如果訪問 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我們能看到來自 NumberService 的 square 方法的日誌消息,以及來自 EventLogger 的 CREATED 事件。 如果隨後刷新瀏覽器,我們只會看到以下內容添加到日誌中:
INFO [nio-8080-exec-2] c.b.cachetest.rest.NumberController : call numberService to square 12在 NumberService 的 square 方法中記錄的消息沒有被調用。這表明緩存值正在被使用。
如果我們等待 30 秒鐘,讓緩存項過期並刷新瀏覽器,我們將會看到 EXPIRED 事件,以及值重新添加到緩存中:
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如果我們在瀏覽器中輸入 http://localhost:8080/number/square/3,我們得到正確答案 9,但值未被緩存。
這是因為我們在 @Cacheable 註解中使用條件,僅緩存大於 10 的數字的值。
6. 結論
在本快速教程中,我們演示瞭如何使用 Spring Boot 設置 Ehcache。