redisTemplate序列化
JdkSerializationRedisSerializer
在没有序列化之前,调用put方法
@Resource
private RedisTemplate<String,String> redisTemplate;
redisTemplate.opsForHash().put(key,"name","张三");
缓存中结果是乱码
这是因为redisTemplate默认为JdkSerializationRedisSerializer序列化
查看对应redis内容
String key = "demo.user.info";
User user = User.builder().id(1).name("张三").count(22.11).birth(
Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())).build();
redisTemplate.opsForHash().put(key,"name","张三");
System.out.println(redisTemplate.boundHashOps(key).keys());
System.out.println(redisTemplate.boundHashOps(key).values());
System.out.println(redisTemplate.boundHashOps(key).entries());
//输出
[name]
[张三]
{name=张三}
虽然这种默认序列化方式显示乱码,但也不会影响我们读取到得数据,只是在缓存中无法直观看到数据内容,很是不便
StringRedisSerializer
通过StringRedisTemplate进行上面相同操作
@Resource
private StringRedisTemplate stringRedisTemplate;
String key = "demo.user.info";
stringRedisTemplate.opsForHash().put(key,"name1","李四");
System.out.println(stringRedisTemplate.boundHashOps(key).entries());
//输出
{name1=李四}
查看缓存中数据
这次缓存中没有乱码,查看源码,看到该类继承并改变了RedisTemplate默认Jdk序列化的方式,由StringRedisSerializer来实现,并和名字呼应
各种序列化对比
目前springboot 2.xx版本主要有这几种不同的序列器
| 名称 | 说明 | 特点 |
|---|---|---|
| GenericJackson2JsonRedisSerializer | 基本和上面的Jackson2JsonRedisSerializer功能差不多,使用方式也差不多 | 不需要指定序列化对象的类型信息 |
| GenericToStringSerializer | 他需要调用者给传一个对象到字符串互转的Converter(相当于转换为字符串的操作交给转换器去做) | 比较不推荐使用,不如StringRedisSerializer方便 |
| Jackson2JsonRedisSerializer | 对象以Json的形式存储,效率高且对调用者友好 | 1:速度快,效率高 2:必须提供要序列化对象的类型信息(.class对象) |
| JacksonJsonRedisSerializer | 已过期 | |
| JdkSerializationRedisSerializer | RestTemplate类默认的序列化方式 | 1:必须实现java.io.Serializable接口,序列化后的数据庞大,比较笨重 2:存储的格式是二进制,不方便直观看数据 |
| OxmSerializer | 以xml格式存储。 | 析起来也比较复杂,效率也比较低 |
| StringRedisSerializer | StringRedisTemplate默认的序列化方式,key和value都会采用此方式进行序列化,是被推荐使用的,对开发者友好,轻量级,效率也比较高 |
Jackson2JsonRedisSerializer
RedisTemplate<String,Object> jackson2JsonRedisTemplate = new RedisTemplate<>();
jackson2JsonRedisTemplate.setConnectionFactory(this.redisConnectionFactory);
jackson2JsonRedisTemplate.setKeySerializer(new StringRedisSerializer());
//指定value的序列化为Jackson2JsonRedisSerializer
jackson2JsonRedisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(User.class));
//设置后必须调用该方法生效 否则会抛出 IllegalArgumentException: template not initialized; call afterPropertiesSet() before using it
jackson2JsonRedisTemplate.afterPropertiesSet();
String key = "demo.user.info";
User user = User.builder().id(1).name("张三").count(22.11).birth(
Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())).build();
jackson2JsonRedisTemplate.opsForValue().set(key,user);
System.out.println(jackson2JsonRedisTemplate.opsForValue().get(key));
//输出
User(id=1, name=张三, count=22.11, birth=Sun Dec 26 16:06:35 CST 2021)
查看redis中数据
new Jackson2JsonRedisSerializer(User.class)初始化是制定了序列化的类型,这种需要指定类型的方式不适合做全局的序列化配置
GenericJackson2JsonRedisSerializer
代码配置如下
RedisTemplate<String,Object> genericRedisTemplate = new RedisTemplate<>();
genericRedisTemplate.setConnectionFactory(this.redisConnectionFactory);
genericRedisTemplate.setKeySerializer(new StringRedisSerializer());
genericRedisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//设置后必须调用该方法生效 否则会抛出 IllegalArgumentException: template not initialized; call afterPropertiesSet() before using it
genericRedisTemplate.afterPropertiesSet();
String key = "demo.user.info";
User user = User.builder().id(1).name("张三").count(22.11).birth(
Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())).build();
genericRedisTemplate.opsForValue().set(key,user);
System.out.println(genericRedisTemplate.opsForValue().get(key));
//输出
User(id=1, name=张三, count=22.11, birth=Sun Dec 26 20:22:10 CST 2021)
查看缓存中的数据
这种序列化方式不用自己手动指定对象的Class,缓存中会有存储数据的类型,比较适合做一个全局的通用序列化配置