我的编程空间,编程开发者的网络收藏夹
学习永远不晚

redis@Cacheable注解以及过期时间设置方式是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

redis@Cacheable注解以及过期时间设置方式是什么

redis@Cacheable注解以及过期时间设置方式是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。


原理解释 

友情链接  手写redis @ Cacheable注解参数java对象作为键值 

@Cacheable注解作用,将带有该注解方法的返回值存放到redis的的中;

使用方法在方法上使用@Cacheable(键=“测试+#P0 + P1#...”)

表示键值为测试+方法第一个参数+方法第二个参数,值为该方法的返回值。

以下源代码表示获取人员列表,Redis的中存放的关键值为'领袖'+ leaderGroupId + UUID + yearDetailId

        @Override@Cacheable(key="'leader'+#p0+#p1+#p2",value="leader")public List<Leader> listLeaders(String leaderGroupId, String uuid, String yearDetailId) {return sysIndexMapper.listLeaders(leaderGroupId, uuid, yearDetailId);}

等同于

        @Overridepublic List<Leader> listLeaders(String leaderGroupId, String uuid, String yearDetailId) {String key = "leader" + leaderGroupId + uuid + yearDetailId;// 判断缓存是否存在redis中boolean hasKey = redisUtil.hasKey(key);if (hasKey) {                        //如果存在 返还redis中的值Object leadersList = redisUtil.get(key);return (List<Leader>) leadersList;} else {List<Leader> leadersQuotaDetailList = sysIndexMapper.listLeaders(leaderGroupId, uuid, yearDetailId);                        //将查询结果存放在redis中redisUtil.set(key, leadersQuotaDetailList);return leadersQuotaDetailList;}}

说白了就是在原方法的前面判断的关键值是否存在的Redis的中,如果存在就取内存中的值,如果不存在就查询数据库,将查询结果存放在Redis的的中。

实现方法

  • 使用代理模式,在方法执行前和执行后可以添加其他处理程序,本文采用springAOP +注解方式。

  • 集成redis,封装Redis工具类

  • 原版本不支持 过期时间 设置,本文将实现

源代码

缓存配置类RedisConfig

package com.huajie.config; import org.springframework.beans.factory.annotation.Value;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.cache.interceptor.KeyGenerator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper; @Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport { @Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Value("${spring.redis.timeout}")private int timeout; // 自定义缓存key生成策略@Beanpublic KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, java.lang.reflect.Method method, Object... params) {StringBuffer sb = new StringBuffer();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};} // 缓存管理器@Beanpublic CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);// 设置缓存过期时间cacheManager.setDefaultExpiration(10000);return cacheManager;} @Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(factory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key采用String的序列化方式template.setKeySerializer(stringRedisSerializer);// hash的key也采用String的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;} private void setSerializer(StringRedisTemplate template) {@SuppressWarnings({ "rawtypes", "unchecked" })Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setValueSerializer(jackson2JsonRedisSerializer);}}

Redis的依赖引入,配置文件,工具类RedisUtil,网上几个版本都类似,本文参考以下版本传送门

https://www.yisu.com/article/233562.htm

准备工作做好之后开始正式编写注解@Cacheable nextkey()用做二级缓存本文中不会用到

nextKey用法详情> 设计模式(实战) - 责任链模式 <

创建的Java的注解@ExtCacheable  

package com.huajie.annotation; import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Target({ ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface ExtCacheable {String key() default "";String nextKey() default ""; int expireTime() default 1800;//30分钟}
 

SpringAop切面CacheableAspect

package com.huajie.aspect; import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import org.aspectj.lang.ProceedingJoinPoint;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.stereotype.Component;import com.huajie.annotation.ExtCacheable;import com.huajie.utils.RedisUtil; @Component@Aspectpublic class CacheableAspect {@Autowiredprivate RedisUtil redisUtil; @Pointcut("@annotation(com.huajie.annotation.ExtCacheable)")public void annotationPointcut() {} @Around("annotationPointcut()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {// 获得当前访问的classClass<?> className = joinPoint.getTarget().getClass();// 获得访问的方法名String methodName = joinPoint.getSignature().getName();// 得到方法的参数的类型Class<?>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();Object[] args = joinPoint.getArgs();String key = "";int expireTime = 1800;try {// 得到访问的方法对象Method method = className.getMethod(methodName, argClass);method.setAccessible(true);// 判断是否存在@ExtCacheable注解if (method.isAnnotationPresent(ExtCacheable.class)) {ExtCacheable annotation = method.getAnnotation(ExtCacheable.class);key = getRedisKey(args,annotation);expireTime = getExpireTime(annotation);}} catch (Exception e) {throw new RuntimeException("redis缓存注解参数异常", e);}// 获取缓存是否存在boolean hasKey = redisUtil.hasKey(key);if (hasKey) {return redisUtil.get(key);} else {                         //执行原方法(java反射执行method获取结果)Object res = joinPoint.proceed();                         //设置缓存redisUtil.set(key, res);                         //设置过期时间redisUtil.expire(key, expireTime);return res;}}private int getExpireTime(ExtCacheable annotation) {return annotation.expireTime();} private String getRedisKey(Object[] args,ExtCacheable annotation) {String primalKey = annotation.key();//获取#p0...集合List<String> keyList = getKeyParsList(primalKey);for (String keyName : keyList) {int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", ""));Object parValue = args[keyIndex];primalKey = primalKey.replace(keyName, String.valueOf(parValue));}return primalKey.replace("+","").replace("'","");} // 获取key中#p0中的参数名称private static List<String> getKeyParsList(String key) {List<String> ListPar = new ArrayList<String>();if (key.indexOf("#") >= 0) {int plusIndex = key.substring(key.indexOf("#")).indexOf("+");int indexNext = 0;String parName = "";int indexPre = key.indexOf("#");if(plusIndex>0){indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+");parName = key.substring(indexPre, indexNext);}else{parName = key.substring(indexPre);}ListPar.add(parName.trim());key = key.substring(indexNext + 1);if (key.indexOf("#") >= 0) {ListPar.addAll(getKeyParsList(key));}}return ListPar;}}

业务模块使用方法

@Override@ExtCacheable(key = "Leaders+#p0+#p1+#p2")// 手机端获取领导人员列表public List<Leader> listLeaders(String leaderGroupId, String uuid, String yearDetailId) {List<Leader> leadersQuotaDetailList = sysIndexMapper.listLeaders(leaderGroupId, uuid, yearDetailId);return leadersQuotaDetailList;}

业务模块过期时间使用方法,5分钟过期

@Override@ExtCacheable(key = "mobileCacheFlag", expireTime = 60 * 5)public int cacheFlag() {int mobileCacheFlag = 1;mobileCacheFlag = sysIndexMapper.cacheFlag();return mobileCacheFlag;}

Redis的的截图

redis@Cacheable注解以及过期时间设置方式是什么

关于redis@Cacheable注解以及过期时间设置方式是什么问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网行业资讯频道了解更多相关知识。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

redis@Cacheable注解以及过期时间设置方式是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

redis@Cacheable注解以及过期时间设置方式是什么

redis@Cacheable注解以及过期时间设置方式是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。原理解释 友情链接 手写redis @ Cacheable注解参
2023-06-22

Java操作redis设置第二天凌晨过期的解决方案是什么

这期内容当中小编将会给大家带来有关Java操作redis设置第二天凌晨过期的解决方案是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java操作redis设置第二天凌晨过期场景在做查询数据的时候,遇到
2023-06-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录