refactor(缓存): 重构Caffeine缓存模板以支持自定义过期时间

重构AbstractCaffeineCacheTemplate使其支持自定义过期和刷新时间配置
为不同业务场景的缓存实例配置合理的过期时间
This commit is contained in:
dzq 2025-11-06 10:28:05 +08:00
parent 147194a116
commit 509d57596f
2 changed files with 72 additions and 29 deletions

View File

@ -21,7 +21,10 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class CaffeineCacheService {
public AbstractCaffeineCacheTemplate<String> captchaCache = new AbstractCaffeineCacheTemplate<String>() {
// 验证码缓存5分钟过期和刷新验证码通常短时间内有效
public AbstractCaffeineCacheTemplate<String> captchaCache = new AbstractCaffeineCacheTemplate<String>(
5, java.util.concurrent.TimeUnit.MINUTES,
5, java.util.concurrent.TimeUnit.MINUTES) {
@Override
public String getObjectFromDb(Object id) {
// 验证码通常不需要从数据库获取这里返回null
@ -29,7 +32,10 @@ public class CaffeineCacheService {
}
};
public AbstractCaffeineCacheTemplate<SystemLoginUser> loginUserCache = new AbstractCaffeineCacheTemplate<SystemLoginUser>() {
// 登录用户缓存1小时过期和刷新登录态保持
public AbstractCaffeineCacheTemplate<SystemLoginUser> loginUserCache = new AbstractCaffeineCacheTemplate<SystemLoginUser>(
12, java.util.concurrent.TimeUnit.HOURS,
12, java.util.concurrent.TimeUnit.HOURS) {
@Override
public SystemLoginUser getObjectFromDb(Object id) {
// 登录用户信息通常不需要从数据库获取这里返回null
@ -37,7 +43,10 @@ public class CaffeineCacheService {
}
};
public AbstractCaffeineCacheTemplate<SysUserEntity> userCache = new AbstractCaffeineCacheTemplate<SysUserEntity>() {
// 用户信息缓存2小时过期和刷新用户信息相对稳定但可能更新
public AbstractCaffeineCacheTemplate<SysUserEntity> userCache = new AbstractCaffeineCacheTemplate<SysUserEntity>(
12, java.util.concurrent.TimeUnit.HOURS,
12, java.util.concurrent.TimeUnit.HOURS) {
@Override
public SysUserEntity getObjectFromDb(Object id) {
SysUserService userService = cn.hutool.extra.spring.SpringUtil.getBean(SysUserService.class);
@ -45,7 +54,10 @@ public class CaffeineCacheService {
}
};
public AbstractCaffeineCacheTemplate<SysRoleEntity> roleCache = new AbstractCaffeineCacheTemplate<SysRoleEntity>() {
// 角色缓存24小时过期和刷新角色信息很少变更
public AbstractCaffeineCacheTemplate<SysRoleEntity> roleCache = new AbstractCaffeineCacheTemplate<SysRoleEntity>(
24, java.util.concurrent.TimeUnit.HOURS,
24, java.util.concurrent.TimeUnit.HOURS) {
@Override
public SysRoleEntity getObjectFromDb(Object id) {
SysRoleService roleService = cn.hutool.extra.spring.SpringUtil.getBean(SysRoleService.class);
@ -53,7 +65,10 @@ public class CaffeineCacheService {
}
};
public AbstractCaffeineCacheTemplate<SysPostEntity> postCache = new AbstractCaffeineCacheTemplate<SysPostEntity>() {
// 岗位缓存24小时过期和刷新岗位信息很少变更
public AbstractCaffeineCacheTemplate<SysPostEntity> postCache = new AbstractCaffeineCacheTemplate<SysPostEntity>(
24, java.util.concurrent.TimeUnit.HOURS,
24, java.util.concurrent.TimeUnit.HOURS) {
@Override
public SysPostEntity getObjectFromDb(Object id) {
SysPostService postService = cn.hutool.extra.spring.SpringUtil.getBean(SysPostService.class);
@ -61,7 +76,10 @@ public class CaffeineCacheService {
}
};
public AbstractCaffeineCacheTemplate<String> qyUseridCache = new AbstractCaffeineCacheTemplate<String>() {
// 企业微信用户ID缓存6小时过期和刷新通过API获取有一定成本
public AbstractCaffeineCacheTemplate<String> qyUseridCache = new AbstractCaffeineCacheTemplate<String>(
12, java.util.concurrent.TimeUnit.HOURS,
12, java.util.concurrent.TimeUnit.HOURS) {
@Override
public String getObjectFromDb(Object id) {
// 企业微信用户ID需要通过API获取这里返回null由调用方处理

View File

@ -6,7 +6,6 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@ -17,28 +16,53 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractCaffeineCacheTemplate<T> {
private final LoadingCache<String, Optional<T>> caffeineCache = Caffeine.newBuilder()
// 基于容量回收缓存的最大数量
.maximumSize(1024)
// 基于容量回收但这是统计占用内存大小maximumWeight与maximumSize不能同时使用
// .maximumWeight(1000)
// 设置权重可当成每个缓存占用的大小
// .weigher((key, value) -> 1)
// 设置软引用值
.softValues()
// 设置过期时间 - 最后一次写入后经过固定时间过期
.expireAfterWrite(10, TimeUnit.HOURS)
// 设置刷新时间 - 写入后经过固定时间刷新
.refreshAfterWrite(10, TimeUnit.HOURS)
// 所有segment的初始总容量大小
.initialCapacity(128)
// 开启缓存统计
.recordStats()
// 移除监听器
.removalListener((key, value, cause) -> {
log.debug("触发删除动作删除的key={}, 原因={}", key, cause);
})
.build(new CacheLoader<String, Optional<T>>() {
private final LoadingCache<String, Optional<T>> caffeineCache;
/**
* 默认构造函数使用10小时的过期时间和刷新时间
*/
public AbstractCaffeineCacheTemplate() {
this(10, TimeUnit.HOURS, 10, TimeUnit.HOURS);
}
/**
* 构造函数支持自定义过期时间和刷新时间
* @param expireAfterWriteDuration 过期时间数值
* @param expireAfterWriteUnit 过期时间单位
* @param refreshAfterWriteDuration 刷新时间数值
* @param refreshAfterWriteUnit 刷新时间单位
*/
public AbstractCaffeineCacheTemplate(long expireAfterWriteDuration, TimeUnit expireAfterWriteUnit,
long refreshAfterWriteDuration, TimeUnit refreshAfterWriteUnit) {
Caffeine<Object, Object> caffeineBuilder = Caffeine.newBuilder()
// 基于容量回收缓存的最大数量
.maximumSize(1024)
// 基于容量回收但这是统计占用内存大小maximumWeight与maximumSize不能同时使用
// .maximumWeight(1000)
// 设置权重可当成每个缓存占用的大小
// .weigher((key, value) -> 1)
// 设置软引用值
.softValues()
// 所有segment的初始总容量大小
.initialCapacity(128)
// 开启缓存统计
.recordStats()
// 移除监听器
.removalListener((key, value, cause) -> {
log.debug("触发删除动作删除的key={}, 原因={}", key, cause);
});
// 如果过期时间大于0则设置过期策略
if (expireAfterWriteDuration > 0) {
caffeineBuilder.expireAfterWrite(expireAfterWriteDuration, expireAfterWriteUnit);
}
// 如果刷新时间大于0则设置刷新策略
if (refreshAfterWriteDuration > 0) {
caffeineBuilder.refreshAfterWrite(refreshAfterWriteDuration, refreshAfterWriteUnit);
}
this.caffeineCache = caffeineBuilder.build(new CacheLoader<String, Optional<T>>() {
@Override
public Optional<T> load(String key) {
T cacheObject = getObjectFromDb(key);
@ -55,6 +79,7 @@ public abstract class AbstractCaffeineCacheTemplate<T> {
}, executor);
}
});
}
/**
* 从缓存中获取对象