用泛型写Redis缓存与数据库操作工具类
功能描述: 先从缓存获取数据,如果缓存没有,就从数据库获取数据,并设置到缓存中,返回数据。
如果数据库中没有数据,需要设置一个缓存标记flagKey,防止暴击访问数据库,用缓存保护数据库。
当删除缓存key时,需要同时删除flagKey,保证数据库可被访问。
关于java泛型的知识点,这里就跳过了。不理解的就自己去百度一下。
直接上代码:
1.先定义泛型接口,用于写从数据库获取数据的方法。
/** * 普通数据获取器 * */ public interface DataGeter<T> { /** * 获取数据接口 * @return */ public T getData(); }
2.工具类。有一些方法需要自己写,看注释。
public class DataUtil { /**json转换工具*/ private static Gson gson = new Gson(); /**一天的过期秒数*/ private static final int ONE_DAY_EXPIRE_SECONDS = 1 * 24 * 60 * 60; /** * 获取redis中获取指定data,如果redis中不存在,则从DataGeter接口中获取,并且写入redis<br/> * 注:该方法会自动创建一个cacheKey + "_flag"的缓存key,作为标记flagKey * @param cacheKey-缓存key * @param clazz-获取目标类型 * @param dataGeter-数据获取器,原始数据源 * @param expireSeconds-缓存失效时间 * @return */ public static <T> T getDataFromRedisOrDataGeter(String cacheKey, Class<T> clazz, DataGeter<T> dataGeter,int expireSeconds) { T val = RedisClient.getValue(cacheKey, clazz); if (val != null) { //让热数据一直热下去 <单个key/value>,设置缓存有效期。 haveChanceToSetKeyExpireTime( cacheKey, expireSeconds) ; return val; } if (RedisClient.existsKey(RedisClient.getFlagKey(cacheKey))) { return null; } try {
//本地锁 Object lockObject = LockObjectUtil.getLockObject(cacheKey); synchronized (lockObject) {// 为提升性能 这里不使用分布式锁 // 标记key,防止集合为空时还不停从数据库中读取数据 T data = null; try { data = dataGeter.getData(); } catch (DBException e) { e.printStackTrace(); throw e; } if (data != null) { // 这里最后才设置flag,以免分布式环境下dataGeter.getData();获取慢,导致后续请求从缓存中取不到数据 //有值不设置flag RedisClient.setValue(cacheKey, data, expireSeconds <= 0 ? RedisDataSource.DEFAULT_EXPIRE_SECONDS : expireSeconds, false); } else { // 不存在数据则往缓存中插入一个flag,过期时间为一天 RedisClient.setValue(RedisClient.getFlagKey(cacheKey), true, ONE_DAY_EXPIRE_SECONDS); } return data; } } finally { //释放锁 LockObjectUtil.disposeLock(cacheKey); } } }
当调用工具类的方法时,写匿名内部类,去实现从数据库获取数据的逻辑。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!