对比同份数据初次序列化时的情况(很多帖子都没有考虑序列化的同份数据是否为二次加载的情况,就给出了结论)
Jackson2JsonRedisSerializer
[
{
"id": "1",
"parentId": "2",
"content": "Node1",
"children": null
},
{
"id": null,
"parentId": null,
"content": null,
"children": null
}
]
GenericJackson2JsonRedisSerializer
[
"java.util.ArrayList",
[
{
"@class": "life.cqq.blog.common.entity.Toc",
"id": "1",
"parentId": "2",
"content": "Node1",
"children": null
},
{
"@class": "life.cqq.blog.common.entity.Toc",
"id": null,
"parentId": null,
"content": null,
"children": null
}
]
]
上面分别是两种序列化方式的结果,
GenericJackson2JsonRedisSerializer根据额外插入的类全限定名通过反射可以正确得到实体类的实例。
而Jackson2JsonRedisSerializer由于没有插入额外的信息,那么只能通过不同的数据结构来组装反序列化后的内容。例如上面的Json串反序列化的结果类型为: ArrayList
为什么会这样?
二者本质都是使用的ObjectMapper,只不过GenericJackson2JsonRedisSerializer在内部对ObjectMapper进行了特定配置而已:
public GenericJackson2JsonRedisSerializer() {
this((String) null);
}
public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName) {
this(new ObjectMapper());
registerNullValueSerializer(mapper, classPropertyTypeName);
// 下面的配置就是在序列化结果中加入实体类全限定名的配置
if (StringUtils.hasText(classPropertyTypeName)) {
mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, classPropertyTypeName);
} else {
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
}
}
public GenericJackson2JsonRedisSerializer(ObjectMapper mapper) {
Assert.notNull(mapper, "ObjectMapper must not be null!");
this.mapper = mapper;
}
使用Jackson2JsonRedisSerializer时,可以自己创建一个ObjectMapper对象,并进行上面的配置后,通过构造方法进行传递。那么最后Jackson2JsonRedisSerializer的序列化效果和GenericJackson2JsonRedisSerializer是一样的。
根据以上内容,给出一份RedisTemplate的常用配置:
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
// key 采用StringRedisSerializer
// value 采用GenericJackson2JsonRedisSerializer
RedisTemplate template = new RedisTemplate<>();
// 关闭启用默认配置
template.setEnableDefaultSerializer(false);
// 连接工厂
template.setConnectionFactory(factory);
// key 序列化方式
template.setKeySerializer(RedisSerializer.string());
// value 序列化方式
template.setValueSerializer(RedisSerializer.json());
// hash key 序列化方式
template.setHashKeySerializer(RedisSerializer.string());
// hash value 序列化方式
template.setHashValueSerializer(RedisSerializer.json());
// 配置完成
template.afterPropertiesSet();
return template;
}