本章将介绍 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 映射之上的序列化器适配器。