SpringBoot结合Redis实现序列化的方法详解
目录
- 前言
- 配置类
- 配置 Jackson2JsonRedisSerializer 序列化策略
- 配置RedisTemplate
- 配置缓存策略
- 测试代码
- 完整代码
前言 最近在学习Spring Boot结合Redis时看了一些网上的教程,发现这些教程要么比较老,要么不知道从哪抄得,运行起来有问题。这里分享一下我最新学到的写法
默认情况下,Spring 为我们提供了一个 RedisTemplate 来进行对 Redis 的操作,但是 RedisTemplate 默认配置的是使用Java本机序列化。
这种序列化方式,对于操作字符串或数字来说,用起来还行,但是如果要对对象操作,就不是那么的方便了。
所以我们需要配置合适的序列化方式。在 Spring 官方的文档中,官方也建议了我们使用其他的方式来进行序列化。比如JSON
文章图片
https://docs.spring.io/spring-data/redis/docs/2.2.5.RELEASE/reference/html/#redis:serializer
配置类 【SpringBoot结合Redis实现序列化的方法详解】
配置 Jackson2JsonRedisSerializer 序列化策略
下面就开始自动配置类的书写
我使用的是 Jackson2JsonRedisSerializer 来对对象进行序列化,所以首先需要一个方法,来配置 Jackson2JsonRedisSerializer 序列化策略
private Jackson2JsonRedisSerializer
这里要注意的是
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
这一句,这一句非常的重要,作用是序列化时将对象全类名一起保存下来
设置之后的序列化结果如下:
[不设置的话,序列化结果如下,将无法反序列化
"com.buguagaoshu.redis.model.User",
{
"name": "1",
"age": "11",
"message": "牛逼"
}
]
{一开始,我在网上搜了一下,发现大多数教程因为时间的原因,这一句用的是
"name": "1",
"age": "11",
"message": "牛逼"
}
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
但当我把这段代码写入的时候,发现Idea提示我
文章图片
着是一个过时的方法,由于我当时并不知道这句话的意思,就把这段代码注释了,觉得可能没什么用,但注释后在向Redis里写数据的时候,数据会变成
文章图片
文章图片
导致数据无法反序列化。
最后我查看了这个方法的源码,找到了
文章图片
文章图片
通过注释,我得到了这段代码的最新写法。
也明白了这段代码的作用。
配置RedisTemplate
@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值redisTemplate.setValueSerializer(serializer()); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // 使用StringRedisSerializer来序列化和反序列化redis的key值redisTemplate.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式redisTemplate.setHashKeySerializer(stringRedisSerializer); // hash的value序列化方式采用jacksonredisTemplate.setHashValueSerializer(serializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; }
这里就没有什么需要注意的了,按照自己的需求,来配置序列化的方式
配置缓存策略
@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer redisSerializer = new StringRedisSerializer(); // 配置序列化(解决乱码的问题)RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()// 缓存有效期.entryTtl(timeToLive)// 使用StringRedisSerializer来序列化和反序列化redis的key值.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer()))// 禁用空值.disableCachingNullValues(); return RedisCacheManager.builder(factory).cacheDefaults(config).build(); }
测试代码
@SpringBootTestpublic class RedisApplicationTests {@Autowiredprivate RedisTemplate redisTemplate; @Testvoid contextLoads() throws Exception {User user = new User(); user.setName("15"); user.setAge(20); user.setMessage("牛逼"); redisTemplate.opsForValue().set(user.getName(), user); User getUser = (User) redisTemplate.opsForValue().get(user.getName()); System.out.println(getUser); System.out.println(getUser.getMessage()); }}
再来查看Redis中的数据
文章图片
数据正常,并且系统也能正常的反序列化了。
完整代码
package com.buguagaoshu.redis.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; 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.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; /** * @author Pu Zhiwei {@literal puzhiweipuzhiwei@foxmail.com} * create2020-03-17 21:08 * 继承 CachingConfigurerSupport,为了自定义生成 KEY 的策略。可以不继承。 */@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {@Value("${spring.cache.redis.time-to-live}")private Duration timeToLive = Duration.ZERO; /*** 配置Jackson2JsonRedisSerializer序列化策略* */private Jackson2JsonRedisSerializerserializer() {// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper objectMapper = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicobjectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); return jackson2JsonRedisSerializer; }@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值redisTemplate.setValueSerializer(serializer()); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // 使用StringRedisSerializer来序列化和反序列化redis的key值redisTemplate.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式redisTemplate.setHashKeySerializer(stringRedisSerializer); // hash的value序列化方式采用jacksonredisTemplate.setHashValueSerializer(serializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; }@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer redisSerializer = new StringRedisSerializer(); // 配置序列化(解决乱码的问题)RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()// 缓存有效期.entryTtl(timeToLive)// 使用StringRedisSerializer来序列化和反序列化redis的key值.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer()))// 禁用空值.disableCachingNullValues(); return RedisCacheManager.builder(factory).cacheDefaults(config).build(); }}
以上就是SpringBoot结合Redis实现序列化的方法详解的详细内容,更多关于SpringBoot Redis序列化的资料请关注脚本之家其它相关文章!
推荐阅读
- Docker安装Redis配置远程连接及踩坑
- 超适合初学者的SpringBoot入门学习笔记,收藏起来慢慢看!
- Redis服务的主从复制哨兵Cluster
- SpringBoot Redis五种数据类型的简单操作
- 图文详解 epoll 原理Redis,Netty,Nginx实现高性能IO的核心原理epoll 详解
- 带你掌握Redis数据类型(string和Hash)
- 基于Redis分布式BitMap的应用
- SpringBoot整合Redis实现简单的Pub/Sub(发布/订阅)
- Linux|Redis(测试连接, 五大数据类型,三种特殊数据类型)
- Redis|【Redis高手修炼之路】初学Redis——概述以及Redis安装使用教程