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

如何将基于Caffeine的Java Spring Cache设置为每日0点和12点定时过期刷新?

实现Caffeine Cache每日固定时间点(0点/12点)过期刷新

当然可以实现!你当前用的expireAfterWrite(12, TimeUnit.HOURS)是相对过期策略(写入后固定时长过期),而你需要的是绝对固定时间点过期——不管缓存什么时候写入,都只在每日的0点和12点触发过期刷新。Caffeine支持通过自定义Expiry接口来实现这种自定义过期逻辑,下面是具体的实现方案:

步骤1:自定义固定时间过期策略

我们需要实现Expiry接口,重写三个方法来统一返回缓存到下一个0点或12点的剩余时长。用Java 8的LocalDateTime处理时间计算会更清晰直观:

import com.github.benmanes.caffeine.cache.Expiry;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

public class DailyFixedTimeExpiry<K, V> implements Expiry<K, V> {

    @Override
    public long expireAfterCreate(K key, V value, long currentTime) {
        // 计算当前时间到下一个0点/12点的毫秒数
        return calculateNextExpiryMillis();
    }

    @Override
    public long expireAfterUpdate(K key, V value, long currentTime, long currentDuration) {
        // 更新缓存时,重新对齐到下一个固定过期点
        return calculateNextExpiryMillis();
    }

    @Override
    public long expireAfterRead(K key, V value, long currentTime, long currentDuration) {
        // 读取缓存不改变过期时间,保持原有的固定过期点
        return currentDuration;
    }

    private long calculateNextExpiryMillis() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nextExpiry;

        // 根据当前时间判断下一个过期点
        if (now.getHour() < 12) {
            // 当前早于12点,下一个过期点是当天12点整
            nextExpiry = now.withHour(12).withMinute(0).withSecond(0).withNano(0);
        } else {
            // 当前晚于/等于12点,下一个过期点是次日0点整
            nextExpiry = now.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        }

        // 计算两个时间点的毫秒差
        return ChronoUnit.MILLIS.between(now, nextExpiry);
    }
}

步骤2:修改CacheConfig配置

把原来的expireAfterWrite替换为expireAfter,传入我们自定义的过期策略即可:

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Component;

@Component
@EnableCaching
public class CacheConfig {
    @Bean
    public Caffeine defaultCacheConfig() {
        return Caffeine.newBuilder()
                // 启用自定义的固定时间过期策略
                .expireAfter(new DailyFixedTimeExpiry<>());
    }
}

关键逻辑说明

  • expireAfterCreate:缓存创建时直接计算到下一个固定时间点的剩余时长,确保缓存只会在0点/12点过期
  • expireAfterUpdate:更新缓存时重新计算过期时间,避免更新后打乱固定过期节奏
  • expireAfterRead:读取缓存不修改过期时间,防止频繁读取导致过期点被无端重置
  • 时间计算:通过判断当前小时数,自动匹配最近的0点或12点,确保缓存严格对齐你需要的刷新时间

额外注意事项

  1. 时区适配:上面的代码使用系统默认时区,如果需要指定特定时区(比如UTC),可以在LocalDateTime.now()时传入ZoneId,例如LocalDateTime.now(ZoneId.of("UTC"))
  2. 自动刷新:如果需要缓存过期后自动加载最新数据,需要结合CacheLoader使用(比如Caffeine.newBuilder().build(cacheLoader)),这样缓存过期时会自动调用加载方法刷新数据
  3. 测试验证:可以通过模拟不同时间点创建缓存,查看过期时长是否符合预期(比如上午10点创建,过期时长应为3小时)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:07:35