首页 > 解决方案 > 如何在spring Cacheable中根据响应对象设置ttl

问题描述

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

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

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

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

标签: springspring-bootspring-cache

解决方案


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

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

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

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

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

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

例如,我为Apache Geode开发 Spring Boot、Session 和 Data ,它可以作为Spring 的 Cache Abstraction中的缓存提供程序。

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

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

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

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

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

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

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



推荐阅读