本章将介绍 Spring Data Redis 内置的序列化器。
该序列化器实现了字符串到 byte[] 的序列化,以及 byte[] 到字符串的反序列化。它使用指定的字符集(默认为 UTF-8)将字符串转换为 byte[],反之亦然。注意,RedisSerializer 接口的定义是一个泛型,如下:
public interface RedisSerializer<T> {}StringRedisSerializer 实现了 RedisSerializer 接口,并且指定接口的泛型为 String。源码如下:
public class StringRedisSerializer implements RedisSerializer<String> {
//...省略代码...
//序列化实现
@Override
public byte[] serialize(@Nullable String string) {
return (string == null ? null : string.getBytes(charset));
}
// 反序列化实现
@Override
public String deserialize(@Nullable byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
}该序列化器实现将 Java 对象到 JSON 字符串的序列化,以及 JSON 字符串到 Java 对象的反序列化。示例:
// 1.配置 RedisTemplate
@Bean
public RedisTemplate<String,Object> genericJackson2JsonSerialRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
// 2.示例代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class GenericJackson2JsonRedisSerializerTest {
@Autowired
@Qualifier("genericJackson2JsonSerialRedisTemplate")
private RedisTemplate<String,Object> template;
@Test
public void demo() {
ValueOperations<String,Object> ops = template.opsForValue();
// 用户数据
User user = new User();
user.setId(1000);
user.setName("ZhangSan");
// 保存
ops.set("key", user);
// 获取
User value = (User)ops.get("key");
System.out.println(value);
}
}运行示例,输出如下:
User{id=1000, name='ZhangSan'}在 Redis 中存储的内容如下:
{
"@class": "com.hxstrive.redis.serializer.entity.User",
"id": 1000,
"name": "ZhangSan"
}上面的 JSON 中比 User 实体多出了一个 @class 字段,该字段用来告诉序列化器怎样将该数据反序列化为 Java 对象。
可将任何对象泛化为字符串并序列化。
可以使用 Jackson 和 Jackson Databind ObjectMapper 读取和写入 JSON 的 RedisSerializer。
// 1.配置 RedisTemplate
@Bean
public RedisTemplate<String,Object> jsonSerialRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
// 2.示例代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class Jackson2JsonRedisSerializerTest {
@Autowired
@Qualifier("jsonSerialRedisTemplate")
private RedisTemplate<String,Object> template;
@Test
public void demo() {
ValueOperations<String,Object> ops = template.opsForValue();
// 设置值
ops.set("key", new User(100, "ZhangSan"));
// 获取值
Object value = ops.get("key");
System.out.println(value.getClass());
System.out.println(value);
}
}运行示例,输出如下:
class java.util.LinkedHashMap
{id=100, name=ZhangSan}保存在 Redis 中的数据如下:
{
"id": 100,
"name": "ZhangSan"
}此时,在 Redis 中保存的数据并没有 @class 字段,因此不能自动反序列化业务对象,与 GenericJackson2JsonRedisSerializer 不同。
默认的序列化器,如果需要使用该序列化器,被序列化的对象必须实现 Serializable 接口。在存储内容时,除了属性的内容外还存了其它内容在里面,总长度长,且不容易阅读。
示例:将一个 java.util.Date 对象存储到 Redis 中,保存到 Redis 的内容如下:
键名为:
\xAC\xED\x00\x05t\x00\x03key
内容为:
\xAC\xED\x00\x05sr\x00\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01\x83\x8C\xE1-\x18x
Spring 的 O/X 映射之上的序列化器适配器。