千家信息网

SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis

发表于:2025-11-14 作者:千家信息网编辑
千家信息网最后更新 2025年11月14日,这篇文章主要讲解了"SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Sprin
千家信息网最后更新 2025年11月14日SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis

这篇文章主要讲解了"SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis"吧!

首先在Mysql中新建一个表bus_student

然后基于此表使用代码生成,前端Vue与后台各层代码生成并添加菜单。

然后来到后台代码中,在后台框架中已经添加了操作redis的相关依赖和工具类。

但是这里还需要添加aspect依赖

                    org.springframework            spring-aspects            4.3.14.RELEASE        

然后在存放配置类的地方新建新增redis缓存的注解

package com.ruoyi.system.redisAop;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/* * @Author * @Description 新增redis缓存 **/@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface AopCacheEnable {//redis缓存key    String[] key();//redis缓存存活时间默认值(可自定义)long expireTime() default 3600;}

以及删除redis缓存的注解

package com.ruoyi.system.redisAop;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/* * @Description 删除redis缓存注解 **/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AopCacheEvict {//redis中的key值    String[] key();}

然后再新建一个自定义缓存切面具体实现类CacheEnableAspect

存放位置

package com.ruoyi.system.redisAop;import com.ruoyi.system.domain.BusStudent;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;/* * @Description 自定义缓存切面具体实现类 **/@Aspect@Componentpublic class CacheEnableAspect {    @Autowiredpublic RedisTemplate redisCache;/**     * Mapper层切点 使用到了我们定义的 AopCacheEnable 作为切点表达式。     */@Pointcut("@annotation(com.ruoyi.system.redisAop.AopCacheEnable)")public void queryCache() {    }/**     * Mapper层切点 使用到了我们定义的 AopCacheEvict 作为切点表达式。     */@Pointcut("@annotation(com.ruoyi.system.redisAop.AopCacheEvict)")public void ClearCache() {    }    @Around("queryCache()")public Object Interceptor(ProceedingJoinPoint pjp) {        Object result = null;//注解中是否有#标识boolean spelFlg = false;//判断是否需要走数据库查询boolean selectDb = false;//redis中缓存的keyString redisKey = "";//获取当前被切注解的方法名Method method = getMethod(pjp);//获取当前被切方法的注解AopCacheEnable aopCacheEnable = method.getAnnotation(AopCacheEnable.class);//获取方法参数值Object[] arguments = pjp.getArgs();//从注解中获取字符串String[] spels = aopCacheEnable.key();for (String spe1l : spels) {if (spe1l.contains("#")) {//注解中包含#标识,则需要拼接spel字符串,返回redis的存储redisKeyredisKey = spe1l.substring(1) + arguments[0].toString();            } else {//没有参数或者参数是List的方法,在缓存中的keyredisKey = spe1l;            }//取出缓存中的数据result = redisCache.opsForValue().get(redisKey);//缓存是空的,则需要重新查询数据库if (result == null || selectDb) {try {                    result =  pjp.proceed();//从数据库查询到的结果不是空的if (result != null && result instanceof ArrayList) {//将redis中缓存的结果转换成对象listList students = (List) result;//判断方法里面的参数是不是BusStudentif (arguments[0] instanceof BusStudent) {//将rediskey-students 存入到redisredisCache.opsForValue().set(redisKey, students, aopCacheEnable.expireTime(), TimeUnit.SECONDS);                        }                    }                } catch (Throwable e) {                    e.printStackTrace();                }            }        }return result;    }/*** 定义清除缓存逻辑,先操作数据库,后清除缓存*/@Around(value = "ClearCache()")public Object evict(ProceedingJoinPoint pjp) throws Throwable {//redis中缓存的keyMethod method = getMethod(pjp);// 获取方法的注解AopCacheEvict cacheEvict = method.getAnnotation(AopCacheEvict.class);//先操作dbObject result = pjp.proceed();// 获取注解的key值String[] fieldKeys = cacheEvict.key();for (String spe1l : fieldKeys) {//根据key从缓存中删除            redisCache.delete(spe1l);        }return result;    }/**     * 获取被拦截方法对象     */public Method getMethod(ProceedingJoinPoint pjp) {        Signature signature = pjp.getSignature();        MethodSignature methodSignature = (MethodSignature) signature;        Method targetMethod = methodSignature.getMethod();return targetMethod;    }}

注意这里的queryCache和ClearCache,里面切点表达式

分别对应上面自定义的两个AopCacheEnable和AopCacheEvict。

然后在环绕通知的queryCache方法执行前后时

获取被切方法的参数,参数中的key,然后根据key去redis中去查询,

如果查不到,就把方法的返回结果转换成对象List,并存入到redis中,

如果能查到,则将结果返回。

然后找到这个表的查询方法,mapper层,比如要将查询的返回结果存储进redis

    @AopCacheEnable(key = "BusStudent",expireTime = 40)public List selectBusStudentList(BusStudent busStudent);

然后在这个表的新增、编辑、删除的mapper方法上添加

    /**     * 新增学生     *     * @param busStudent 学生     * @return 结果     */@AopCacheEvict(key = "BusStudent")public int insertBusStudent(BusStudent busStudent);/**     * 修改学生     *     * @param busStudent 学生     * @return 结果     */@AopCacheEvict(key = "BusStudent")public int updateBusStudent(BusStudent busStudent);/**     * 删除学生     *     * @param id 学生ID     * @return 结果     */@AopCacheEvict(key = "BusStudent")public int deleteBusStudentById(Integer id);

注意这里的注解上的key要和上面的查询的注解的key一致。

然后启动项目,如果启动时提示:

Consider marking one of the beans as @Primary, updating
the consumer to acce

因为sringboot通过@Autowired注入接口的实现类时发现有多个,也就是有多个类继承了这个接口,spring容器不知道使用哪一个。

找到redis的配置类,在RedisTemplate上添加@Primary注解

验证注解的使用

debug启动项目,在CacheEnableAspect中查询注解中打断点,然后调用查询方法,

就可以看到能进断点,然后就可以根据自己想要的逻辑和效果进行修改注解。

感谢各位的阅读,以上就是"SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis"的内容了,经过本文的学习后,相信大家对SpringBoot中怎么通过自定义缓存注解实现数据库数据缓存到Redis这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

缓存 注解 数据 方法 查询 数据库 结果 参数 学生 切点 代码 后台 对象 表达式 学习 代码生成 内容 切面 多个 字符 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云数据库安全分析 如皋软件开发公司 北京某某某某网络技术有限公司 恢复数据库报错1064 关于网络安全的图片大全 江苏知名软件开发价格 网络安全自查和隐患排查 湖北常规软件开发创新服务 银行网络安全知识宣传总结 大学计算机编程软件开发 网络安全技术员属于部队吗 澳洲大学网络安全专业好吗 网络安全教育主题党课 软件开发阿陈 中华财险软件开发在线测评 计算机与网络技术自学 软件开发要学多少钱 大学生网络安全提案模板 局域网接入因特网dns服务器 2020年服务器主板 软件开发技术施工方案提交时间 网络安全法相关法律体系 大数据和网络技术的区别 网络安全提升课程 2022网络安全事件新闻 用户信息怎么存入数据库的 软件开发需要哪些硬件环境 一年级网络安全教案百度文库 自考财务软件开发考什么数据库 mysql数据库的安全
0