对比新文件 |
| | |
| | | package com.iailab.framework.redis.core; |
| | | |
| | | import cn.hutool.core.util.NumberUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import org.springframework.cache.annotation.Cacheable; |
| | | import org.springframework.data.redis.cache.RedisCache; |
| | | import org.springframework.data.redis.cache.RedisCacheConfiguration; |
| | | import org.springframework.data.redis.cache.RedisCacheManager; |
| | | import org.springframework.data.redis.cache.RedisCacheWriter; |
| | | |
| | | import java.time.Duration; |
| | | |
| | | /** |
| | | * 支持自定义过期时间的 {@link RedisCacheManager} 实现类 |
| | | * |
| | | * 在 {@link Cacheable#cacheNames()} 格式为 "key#ttl" 时,# 后面的 ttl 为过期时间。 |
| | | * 单位为最后一个字母(支持的单位有:d 天,h 小时,m 分钟,s 秒),默认单位为 s 秒 |
| | | * |
| | | * @author iailab |
| | | */ |
| | | public class TimeoutRedisCacheManager extends RedisCacheManager { |
| | | |
| | | private static final String SPLIT = "#"; |
| | | |
| | | public TimeoutRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) { |
| | | super(cacheWriter, defaultCacheConfiguration); |
| | | } |
| | | |
| | | @Override |
| | | protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) { |
| | | if (StrUtil.isEmpty(name)) { |
| | | return super.createRedisCache(name, cacheConfig); |
| | | } |
| | | // 如果使用 # 分隔,大小不为 2,则说明不使用自定义过期时间 |
| | | String[] names = StrUtil.splitToArray(name, SPLIT); |
| | | if (names.length != 2) { |
| | | return super.createRedisCache(name, cacheConfig); |
| | | } |
| | | |
| | | // 核心:通过修改 cacheConfig 的过期时间,实现自定义过期时间 |
| | | if (cacheConfig != null) { |
| | | // 移除 # 后面的 : 以及后面的内容,避免影响解析 |
| | | String ttlStr = StrUtil.subBefore(names[1], StrUtil.COLON, false); // 获得 ttlStr 时间部分 |
| | | names[1] = StrUtil.subAfter(names[1], ttlStr, false); // 移除掉 ttlStr 时间部分 |
| | | // 解析时间 |
| | | Duration duration = parseDuration(ttlStr); |
| | | cacheConfig = cacheConfig.entryTtl(duration); |
| | | } |
| | | |
| | | // 创建 RedisCache 对象,需要忽略掉 ttlStr |
| | | return super.createRedisCache(names[0] + names[1], cacheConfig); |
| | | } |
| | | |
| | | /** |
| | | * 解析过期时间 Duration |
| | | * |
| | | * @param ttlStr 过期时间字符串 |
| | | * @return 过期时间 Duration |
| | | */ |
| | | private Duration parseDuration(String ttlStr) { |
| | | String timeUnit = StrUtil.subSuf(ttlStr, -1); |
| | | switch (timeUnit) { |
| | | case "d": |
| | | return Duration.ofDays(removeDurationSuffix(ttlStr)); |
| | | case "h": |
| | | return Duration.ofHours(removeDurationSuffix(ttlStr)); |
| | | case "m": |
| | | return Duration.ofMinutes(removeDurationSuffix(ttlStr)); |
| | | case "s": |
| | | return Duration.ofSeconds(removeDurationSuffix(ttlStr)); |
| | | default: |
| | | return Duration.ofSeconds(Long.parseLong(ttlStr)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 移除多余的后缀,返回具体的时间 |
| | | * |
| | | * @param ttlStr 过期时间字符串 |
| | | * @return 时间 |
| | | */ |
| | | private Long removeDurationSuffix(String ttlStr) { |
| | | return NumberUtil.parseLong(StrUtil.sub(ttlStr, 0, ttlStr.length() - 1)); |
| | | } |
| | | |
| | | } |