问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

SpringBoot整合Redis做缓存-自定义缓存序列化方式,防止缓存数据乱码问 ...

发布网友 发布时间:2024-09-17 05:49

我来回答

1个回答

热心网友 时间:2024-09-29 09:22

首先是添加依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>${spring-boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>${spring-boot.version}</version></dependency>

我这里用的SpringBoot版本是:2.2.5.RELEASE

jedis与lettuce区别

1、Jedis:

在实现上是直连Redisserver,多线程环境下非线程安全,除非使用连接池,为每个redis实例增加物理连接。

2、Lettuce:

是一种可伸缩,线程安全,完全非阻塞的Redis客户端,多个线程可以共享一个RedisConnection,它利用NettyNIO框架来高效地管理多个连接,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。

我这里项目的配置文件使用的是Lettuce,配置文件内容:

spring:datasource:url:jdbc:mysql://192.168.104.64:3306/spring_boot_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueusername:rootpassword:huauN2021#Redis配置redis:database:0host:192.168.104.102password:huauN@2021port:6379timeout:6000#连接超时时长(毫秒)lettuce:pool:max-active:1024#连接池最大连接数(默认为8,-1表示无限制如果pool已经分配了超过max_active个jedis实例,则此时pool为耗尽)max-wait:10000#最大等待连接时间,单位毫秒默认为-1,表示永不超时,超时会抛出JedisConnectionExceptionmax-idle:10min-idle:5

首先是找下redis的配置类,如果没有则新增改配置类:

packagegc.cnnvd.config;importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;/***<p>*RedisTemplate配置*</p>**@authorlinmengmeng*@date2021-07-21*/@ConfigurationpublicclassRedisTemplateConfig{/***redisTemplate配置*@paramfactory*@return***自定义RedisTemplate的原因:*1、修改泛型方式为<String,Object>,避免繁琐的类型转换*2、将value的序列化方式更改为Jackson2JsonRedisSerializer,因为底层的RedisSerializer序列化value时不会带双引号,而使用Jackson2JsonRedisSerializer序列化String类型时会自动添加双引号。**/@Bean@SuppressWarnings("all")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryfactory){RedisTemplate<String,Object>redisTemplate=newRedisTemplate<String,Object>();redisTemplate.setConnectionFactory(factory);Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);ObjectMappermapper=newObjectMapper();//指定要序列化的域,ANY是包括public和private的mapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);//指定序列化输入的类型,类必须是非final类型的,否则会报错mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(mapper);StringRedisSerializerstringRedisSerializer=newStringRedisSerializer();//设置key采用String的序列化方式redisTemplate.setKeySerializer(stringRedisSerializer);//设置hash的key采用String的序列化方式redisTemplate.setHashKeySerializer(stringRedisSerializer);//设置value采用jackson2的序列化方式redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//设置hash的value采用jackson2的序列化方式redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();returnredisTemplate;}}

如果之前配置过redisTemplate,再次新增这个配置文件启动时就会提示异常,提示redisTemplatebean创建失败,已存在什么的。

接着是RedisCacheConfig:

packagegc.cnnvd.config;importorg.springframework.cache.CacheManager;importorg.springframework.cache.annotation.CachingConfigurerSupport;importorg.springframework.cache.annotation.EnableCaching;importorg.springframework.cache.interceptor.KeyGenerator;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.cache.RedisCacheConfiguration;importorg.springframework.data.redis.cache.RedisCacheManager;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializationContext;importorg.springframework.data.redis.serializer.RedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;importjava.time.Duration;importjava.util.Arrays;/***<p>*RedisCache配置*</p>*@authorgeekidea*@date2018-11-08*/@Configuration@EnableCachingpublicclassRedisCacheConfigextendsCachingConfigurerSupport{@Bean@OverridepublicKeyGeneratorkeyGenerator(){return(target,method,params)->{StringBufferredisKey=newStringBuffer();redisKey.append(target.getClass().getName()).append("-");redisKey.append(method.getName());if(params.length>0){redisKey.append("-").append(Arrays.deepToString(params));}returnredisKey.toString();};}/***redis缓存配置*修改序列化方式,解决缓存乱码*@paramfactory*@return*/@BeanpublicCacheManagercacheManager(RedisConnectionFactoryfactory){RedisSerializer<String>redisSerializer=newStringRedisSerializer();Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);//配置序列化RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig();RedisCacheConfigurationredisCacheConfiguration=config//Key序列化方式redisSerializer.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//value序列化方式jackson2JsonRedisSerializer.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))//设置前缀//.prefixKeysWith("project:")//设置过期时间.entryTtl(Duration.ofSeconds(60*60));RedisCacheManagercacheManager=RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();returncacheManager;}}

我这里直接将注解@EnableScheduling加在配置文件这里了,如果不加这里可以直接在启动类上要加上注解:@EnableScheduling

随便找了一个service方法进行测试:

@Override@Cacheable(value="adminUser",key="#adminUserDetailParam.getId()",unless="#result==null")publicAdminUserDetailVOgetAdminUserDetail(AdminUserDetailParamadminUserDetailParam){AdminUserMergeradminUserMerger=adminUserMapper.selectAdminUserDetail(adminUserDetailParam.getId(),adminUserDetailParam.getVersion());log.info("------------走数据库查询-------------");if(adminUserMerger==null){thrownewBusinessException("用户信息不存在");}AdminUserDetailVOadminUserDetailVO=newAdminUserDetailVO();BeanCopierUtils.copyProperties(adminUserMerger,adminUserDetailVO);returnadminUserDetailVO;}

这里仅在原来基础上加了一行注解@Cacheable(value="adminUser",key="#adminUserDetailParam.getId()",unless="#result==null")其中value为redis的key的前缀,

importcom.alibaba.fastjson.JSONObject;importgc.cnnvd.system.adminuser.param.AdminUserDetailParam;importgc.cnnvd.system.adminuser.service.AdminUserService;importgc.cnnvd.system.adminuser.vo.AdminUserDetailVO;importgc.cnnvd.test.BaseTest;importorg.junit.Test;importorg.springframework.beans.factory.annotation.Autowired;/***@Autherlinmengmeng*@Date2021-07-2019:15*/publicclassQueryTestextendsBaseTest{@AutowiredprivateAdminUserServiceadminUserService;@TestpublicvoidtestGetAdminDetail(){AdminUserDetailParamadminUserDetailParam=newAdminUserDetailParam();adminUserDetailParam.setId("test001");adminUserDetailParam.setVersion(0);AdminUserDetailVOadminUserDetail=adminUserService.getAdminUserDetail(adminUserDetailParam);System.out.println(JSONObject.toJSONString(adminUserDetail));}}

写了测试用例后,运行发现缓存好使了,第一次会走数据库查询,第二次直接走redis缓存。

缓存内容,使用可视化工具查看如下图:

作者:linmengmeng

热心网友 时间:2024-09-29 09:25

首先是添加依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>${spring-boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>${spring-boot.version}</version></dependency>

我这里用的SpringBoot版本是:2.2.5.RELEASE

jedis与lettuce区别

1、Jedis:

在实现上是直连Redisserver,多线程环境下非线程安全,除非使用连接池,为每个redis实例增加物理连接。

2、Lettuce:

是一种可伸缩,线程安全,完全非阻塞的Redis客户端,多个线程可以共享一个RedisConnection,它利用NettyNIO框架来高效地管理多个连接,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。

我这里项目的配置文件使用的是Lettuce,配置文件内容:

spring:datasource:url:jdbc:mysql://192.168.104.64:3306/spring_boot_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueusername:rootpassword:huauN2021#Redis配置redis:database:0host:192.168.104.102password:huauN@2021port:6379timeout:6000#连接超时时长(毫秒)lettuce:pool:max-active:1024#连接池最大连接数(默认为8,-1表示无限制如果pool已经分配了超过max_active个jedis实例,则此时pool为耗尽)max-wait:10000#最大等待连接时间,单位毫秒默认为-1,表示永不超时,超时会抛出JedisConnectionExceptionmax-idle:10min-idle:5

首先是找下redis的配置类,如果没有则新增改配置类:

packagegc.cnnvd.config;importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;/***<p>*RedisTemplate配置*</p>**@authorlinmengmeng*@date2021-07-21*/@ConfigurationpublicclassRedisTemplateConfig{/***redisTemplate配置*@paramfactory*@return***自定义RedisTemplate的原因:*1、修改泛型方式为<String,Object>,避免繁琐的类型转换*2、将value的序列化方式更改为Jackson2JsonRedisSerializer,因为底层的RedisSerializer序列化value时不会带双引号,而使用Jackson2JsonRedisSerializer序列化String类型时会自动添加双引号。**/@Bean@SuppressWarnings("all")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryfactory){RedisTemplate<String,Object>redisTemplate=newRedisTemplate<String,Object>();redisTemplate.setConnectionFactory(factory);Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);ObjectMappermapper=newObjectMapper();//指定要序列化的域,ANY是包括public和private的mapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);//指定序列化输入的类型,类必须是非final类型的,否则会报错mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(mapper);StringRedisSerializerstringRedisSerializer=newStringRedisSerializer();//设置key采用String的序列化方式redisTemplate.setKeySerializer(stringRedisSerializer);//设置hash的key采用String的序列化方式redisTemplate.setHashKeySerializer(stringRedisSerializer);//设置value采用jackson2的序列化方式redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//设置hash的value采用jackson2的序列化方式redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();returnredisTemplate;}}

如果之前配置过redisTemplate,再次新增这个配置文件启动时就会提示异常,提示redisTemplatebean创建失败,已存在什么的。

接着是RedisCacheConfig:

packagegc.cnnvd.config;importorg.springframework.cache.CacheManager;importorg.springframework.cache.annotation.CachingConfigurerSupport;importorg.springframework.cache.annotation.EnableCaching;importorg.springframework.cache.interceptor.KeyGenerator;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.cache.RedisCacheConfiguration;importorg.springframework.data.redis.cache.RedisCacheManager;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializationContext;importorg.springframework.data.redis.serializer.RedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;importjava.time.Duration;importjava.util.Arrays;/***<p>*RedisCache配置*</p>*@authorgeekidea*@date2018-11-08*/@Configuration@EnableCachingpublicclassRedisCacheConfigextendsCachingConfigurerSupport{@Bean@OverridepublicKeyGeneratorkeyGenerator(){return(target,method,params)->{StringBufferredisKey=newStringBuffer();redisKey.append(target.getClass().getName()).append("-");redisKey.append(method.getName());if(params.length>0){redisKey.append("-").append(Arrays.deepToString(params));}returnredisKey.toString();};}/***redis缓存配置*修改序列化方式,解决缓存乱码*@paramfactory*@return*/@BeanpublicCacheManagercacheManager(RedisConnectionFactoryfactory){RedisSerializer<String>redisSerializer=newStringRedisSerializer();Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);//配置序列化RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig();RedisCacheConfigurationredisCacheConfiguration=config//Key序列化方式redisSerializer.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//value序列化方式jackson2JsonRedisSerializer.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))//设置前缀//.prefixKeysWith("project:")//设置过期时间.entryTtl(Duration.ofSeconds(60*60));RedisCacheManagercacheManager=RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();returncacheManager;}}

我这里直接将注解@EnableScheduling加在配置文件这里了,如果不加这里可以直接在启动类上要加上注解:@EnableScheduling

随便找了一个service方法进行测试:

@Override@Cacheable(value="adminUser",key="#adminUserDetailParam.getId()",unless="#result==null")publicAdminUserDetailVOgetAdminUserDetail(AdminUserDetailParamadminUserDetailParam){AdminUserMergeradminUserMerger=adminUserMapper.selectAdminUserDetail(adminUserDetailParam.getId(),adminUserDetailParam.getVersion());log.info("------------走数据库查询-------------");if(adminUserMerger==null){thrownewBusinessException("用户信息不存在");}AdminUserDetailVOadminUserDetailVO=newAdminUserDetailVO();BeanCopierUtils.copyProperties(adminUserMerger,adminUserDetailVO);returnadminUserDetailVO;}

这里仅在原来基础上加了一行注解@Cacheable(value="adminUser",key="#adminUserDetailParam.getId()",unless="#result==null")其中value为redis的key的前缀,

importcom.alibaba.fastjson.JSONObject;importgc.cnnvd.system.adminuser.param.AdminUserDetailParam;importgc.cnnvd.system.adminuser.service.AdminUserService;importgc.cnnvd.system.adminuser.vo.AdminUserDetailVO;importgc.cnnvd.test.BaseTest;importorg.junit.Test;importorg.springframework.beans.factory.annotation.Autowired;/***@Autherlinmengmeng*@Date2021-07-2019:15*/publicclassQueryTestextendsBaseTest{@AutowiredprivateAdminUserServiceadminUserService;@TestpublicvoidtestGetAdminDetail(){AdminUserDetailParamadminUserDetailParam=newAdminUserDetailParam();adminUserDetailParam.setId("test001");adminUserDetailParam.setVersion(0);AdminUserDetailVOadminUserDetail=adminUserService.getAdminUserDetail(adminUserDetailParam);System.out.println(JSONObject.toJSONString(adminUserDetail));}}

写了测试用例后,运行发现缓存好使了,第一次会走数据库查询,第二次直接走redis缓存。

缓存内容,使用可视化工具查看如下图:

作者:linmengmeng

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
玉米仁子饭产自哪里 中国期货交易所的交易品种有哪些? 历史要怎么读,有啥诀窍 高中历史诀窍 年终会活动策划方案 深度解析:第一财经回放,探索财经新风向 逆水寒手游庄园怎么邀请好友同住 逆水寒手游 逆水寒不同区可以一起组队吗? 逆水寒手游 逆水寒怎么进入好友世界? 逆水寒手游 逆水寒怎么去别人的庄园? Redis高级操作:scan实现模糊查询 Redis Client-side Caching实现剖析与源码解读 oppor8207. 手机取卡孔坏了,卡槽也坏了,电话打不进来,只能打出去,去售 ... 取卡的那个小孔好像坏了,我弄了半天没能弄出来,咋办?修的话,要多少钱... 工作了多年一直没有发展的机会,想调换工作岗位,怎么给提领导说,应送... ipadqq怎么下载? 记住我的爱·记住我的坏的txt全集下载地址 请记住我的爱的歌词是什么? 冷色&amp;暖色,傻傻分不清楚?教你如何通过冷暖色调进行颜色分类和应用... 2012年七月份毕业的医学本科生,要是考执业医师资格证的话要求是毕业在... 色彩冷暖色调是一种什么现象 腰花是什么东西 腰花是什么部位 腰花的风味是什么意思? 腰花有什么营养价值 倍斯特充电宝用了三个月,现在自己漏电,这个牌子是劣质产品吗? 《小丑女》结局 人一天拥有多少热量才不会胖 人体能量计算公式 给狗狗洗澡的水温一般多少度 需要注意什么 狗狗洗澡水温 晚上小腿酸胀很难入睡是什么原因 每天晚上小腿酸的都睡不着,明明很早就困了可是腿难受翻来覆去能折腾2... 每天晚上睡到凌晨时,小腿肚子就酸痛难忍,要捏一捏,揉一揉才能缓解一下... 真我gt大师版和iqooneo5哪个好-真我gt大师版和iqooneo5对比怎么选 win10系统更新时断电了怎么解决? 为什么我的win10系统更新不了 铁生锈的具体化学反应过程是怎样的? 清华美院画室清华美院招生 请问清华大学博士后年薪是多少? 为什么 2019 年底了,遇到热点事件微博仍然会崩溃?从技术上 泰安往年冬季最低气温 ...约会时候也是女生找话题,一直期待男生说出口,结果有次约会 两人分手后,女生说等男生有结果吗 1I换算到2K分辨率是多少 消防安全风险评估收费标准 爆破资质等级划 男的,项链(银项链)和手表(运动手表)可以一起戴吗? 健身后的拉伸运动有什么作用 主板bios中的UEFI能改成Legacy吗? 三七粉敷脸的功效与作用 三七粉的禁忌人群