背景
当我们的数据存储到 Redis 的时候,我们的键(key)和值(value)都是通过 Spring 提供的 Serializer 序列化到数据库的。
- RedisTemplate 默认使用的是 JdkSerializationRedisSerializer。
- StringRedisTemplate 默认使用的是 StringRedisSerializer。
序列化的方法
- JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前默认的序列化策略。
- StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。
- JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】
- GenericFastJsonRedisSerializer:另一种javabean与json之间的转换,同时也需要指定Class类型。
- OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】
- FastJsonRedisSerializer:使用 Alibaba Fastjson 处理。
例如:
我们把pojo实例序列化成json格式存储在redis中,指定的Class类为User。
@Configuration//我自定义的redisTemplate
public class RedisConfig{
@Bean("myTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// 我们为了自己开发方便,一般直接使用 <String, Object>
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<User> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(User.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);
// String 的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
下面是我的测试类1,将user实例序列化存入redis
@Test
void test() {
User user=new User("xjszsd",202);
redisTemplate.opsForValue().set("ntmd",user);
System.out.println(redisTemplate.opsForValue().get("ntmd"));
}
其结果如下:
若是其他的类如Student类,就不能序列化存储进去。
@Test
void test2() {
Student student = new Student("gyl", "woman");
redisTemplate.opsForValue().set("ntmdb",student);
System.out.println(redisTemplate.opsForValue().get("ntmdb"));
}
其结果显然报错
使用@Configuration注解来标记配置类,在方法上的@Bean注解交由Spring管理,这样我们就实现了Json来保存对象
注意
1.使用 FastJsonRedisSerializer 配置 fastjson 存 java对象时取出来一直是 JSONObject。
解决如下:
- 使用 GenericFastJsonRedisSerializer 处理序列化。
2.当 Redis 的值中含有类似于 \xac\xed\x00\x05t\x00\x04 。
解决如下:
- 这是使用 redis 自带的序列化方式的问题,reidstemplate 使用的默认的序列化方式有问题,需要调整序列化方式才能在 redis 中正常显示,自定义redisTemplate可以解决。