如何根据spring Cacheable中的响应对象设置ttl

时间:2021-08-01 22:25:23

标签: spring spring-boot spring-cache

我有以下缓存用例。我正在使用 @Cacheable 注释,它看起来像这样:

@Cacheable(cacheNames = "sampleCache", key = "#customerId", cacheResolver = "sampleCacheResolver")
public @ResponseBody SampleResponse getSampleMethod(String customerId) {
}

TTL 在 sampleCacheResolver 中设置。但是我有一个要求,我必须根据响应对象更改 TTL。例如,在响应对象中,如果说 SampleResponse.month 是当前月份,我想将 ttl 设置为 1 分钟,否则我想保留默认值 3 分钟。

由于 sampleCacheResolver 在请求级别被调用,我不确定如何根据响应更新 ttl。

1 个答案:

答案 0 :(得分:0)

开箱即用的 Spring's Cache Abstraction 这是不可能的。

Spring 非常clear,无论是 TTL(生存时间)还是 TTI(空闲超时)过期策略(甚至驱逐策略)都不是由抽象处理的,并且有充分的理由。

Expiration 和 Eviction 实现是特定于缓存提供程序的,当条目过期或被驱逐时,许多实现可能有不同的操作。

将 TTL 应用于响应是相当奇特的,特别是考虑到 TTL 是一个设定的时间范围。

无论如何,您有两个选择。

首先,一些缓存提供程序及其支持的 Spring 位提供与您所寻求的功能接近的功能。

例如,我为 Apache Geode 处理 Spring Boot、Session 和 Data,它们可以在 Spring 的缓存抽象serve as a caching provider

我支持的功能之一是通过基于注释的配置模型的入门级(即实体)过期策略。见here。当然,考虑到 Apache Geode 能够表达自定义过期策略,这可以由 Apache Geode 本身实现。也就是说,使用注解实现入门级 TTL 是基于 Apache Geode 的 CustomExpiry 接口。

处理条目/实体或响应 TTL 的另一种方法是覆盖/扩展 Spring 的缓存抽象。抽象中的 2 个主要接口是 CacheManagerCache 接口。

在您的情况下,您将实现 Cache 接口以包含您需要的 TTL 逻辑。您的 Cache (TTL) 实现将包装实际的缓存提供程序实现(例如 EhCache Cache)。然后您必须实现 CacheManager 接口来包装缓存提供程序 CacheManager 实现(同样,EhCache CacheManager)。您的 CacheManager 实现仅用于在框架调用时创建启用 TTL 的 Cache 实现包装提供程序的 Cache 实现的实例。本质上,您启用 TTL 的 Cache 实现正在增强,或decorating 缓存提供程序的 Cache 实现具有您需要的 TTL 逻辑。

另一种可能的解决方案是使用 Spring AOP。实际上,Spring AOP 处理了许多 Spring 的功能,例如缓存或事务管理(分界)。精心设计的 AOP 方面可以包装缓存方面并包含您需要的 TTL 逻辑。您必须确保 TTL AOP Aspect 出现在 Spring 的 Caching Aspect 之后,可以通过 bean 排序来处理。

这次我没有为您的确切用例提供示例。但是,我之前已经回答过需要对 Spring 的 CacheCacheManager 接口进行“自定义”实现的问题。供您参考,您可以参考我的 example 以了解如何实现您自己的 Cache/CacheManager 组合。

在继续我介绍的路径之前,我鼓励您探索您的缓存提供程序,看看它是否为您提供了您所追求的 TTL 功能。您应该根据自己的需要和要求选择合适的缓存提供程序。

我知道这是很多信息,但我只是想让您有选择并从多个角度思考问题。