You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在每日凌晨12点刷新Spring @Cacheable缓存?

实现每日凌晨12点刷新Ehcache缓存的方案

你提到的timeToIdleSeconds和timeToLiveSeconds确实是相对时间(从缓存条目创建/访问开始计算),没法直接实现“每天固定凌晨12点过期”的绝对时间需求。针对你的场景(用@Cacheable注解),我给你两种可行的实现思路:

方法一:结合Spring定时任务主动清除缓存(推荐,适配Ehcache 2.x/3.x)

这种方式最直接,通过定时任务在每天凌晨12点主动清除指定缓存,下次调用retrieveConfigurations()时会自动重新加载数据。

步骤1:开启Spring调度支持

在你的Spring配置类上添加@EnableScheduling注解,开启定时任务功能:

@Configuration
@EnableScheduling
public class CacheConfig {
    // 其他缓存配置...
}

步骤2:编写定时清除缓存的方法

注入Spring的CacheManager,然后用@Scheduled注解指定凌晨12点的 cron 表达式:

@Component
public class CacheRefreshTask {

    @Autowired
    private CacheManager cacheManager;

    // cron表达式:0秒 0分 0时 每天 每月 任意星期
    @Scheduled(cron = "0 0 0 * * ?")
    public void clearCacheAtMidnight() {
        Cache cache = cacheManager.getCache("cacheName");
        if (cache != null) {
            // 清除该缓存下的所有条目
            cache.clear();
            // 如果需要直接操作Ehcache原生对象(比如Ehcache 2.x的net.sf.ehcache.Cache)
            // ((net.sf.ehcache.Cache) cache.getNativeCache()).removeAll();
        }
    }
}

方法二:自定义Expiry实现绝对时间过期(仅Ehcache 3.x适用)

如果你用的是Ehcache 3.x(包路径为org.ehcache),可以通过实现Expiry接口,让每个缓存条目自动计算到次日凌晨12点的剩余过期时间。

自定义Expiry类

public class MidnightExpiry implements Expiry<Object, Object> {

    @Override
    public Duration getExpiryForCreation(Object key, Object value) {
        // 计算当前时间到次日凌晨12点的时间差
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nextMidnight = now.plusDays(1)
                                       .withHour(0)
                                       .withMinute(0)
                                       .withSecond(0)
                                       .withNano(0);
        return Duration.between(now, nextMidnight);
    }

    @Override
    public Duration getExpiryForAccess(Object key, ValueSupplier<?> value) {
        // 访问缓存时不延长过期时间,保持到凌晨过期
        return null;
    }

    @Override
    public Duration getExpiryForUpdate(Object key, ValueSupplier<?> oldValue, Object newValue) {
        // 更新缓存时重新计算到凌晨的过期时间
        return getExpiryForCreation(key, newValue);
    }
}

配置缓存时使用该Expiry

在构建CacheConfiguration时指定自定义的过期策略:

@Bean
public CacheManager cacheManager() {
    CacheConfiguration<Object, Object> cacheConfig = CacheConfigurationBuilder
            .newCacheConfigurationBuilder(Object.class, Object.class, ResourcePoolsBuilder.heap(100))
            .withExpiry(new MidnightExpiry())
            .build();

    return EhcacheManagerBuilder.newCacheManagerBuilder()
            .withCache("cacheName", cacheConfig)
            .build(true);
}

两种方案的区别

  • 定时清除:不管缓存条目什么时候创建,每天凌晨12点统一清除,适合需要强制刷新数据的场景。
  • 自定义Expiry:每个条目创建后,会自动到次日凌晨过期,如果是当天下午创建的缓存,会保留到第二天凌晨,适合允许缓存保留到当天结束的场景。

内容的提问来源于stack exchange,提问作者karfai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:58:11