1.redis序列化器作用
在保存数据时需要把java对象序列化为byte,在读取数据时需要把byte反序列化为java对象;
不同的java数据类型序列化和反序列化的逻辑不一样;
java对象序列化后的文本格式不一样。常见的有java对象字节码、json字符串,xml字符串;
spring把上述逻辑封闭在redis序列化器中,接口为RedisSerializer;
2.redis序列化器结构
3.序列化器解析
3.1.RedisSerializer接口
提供了序列化serialize和反序列化deserialize两个接口;
提供了几个静态方法,每个静态方法针对不同java对象序列化后的文本格式;
提供了getTargetType和canSerialize两个接口,提供此序列化器针对的数据类型;
//**把对象序列化为byte数组
byte[] serialize(@Nullable T t) throws SerializationException;
//**把byte数组反序列化为对象
T deserialize(@Nullable byte[] bytes) throws SerializationException;
//**静态方法,java格式序列化器
static RedisSerializer java() {
return java(null);
}
//**静态方法,java格式序列化器
static RedisSerializer java(@Nullable ClassLoader classLoader) {
return new JdkSerializationRedisSerializer(classLoader);
}
//**静态方法,json格式序列化器
static RedisSerializer json() {
return new GenericJackson2JsonRedisSerializer();
}
//**静态方法,string数据类型序列化器
static RedisSerializer string() {
return StringRedisSerializer.UTF_8;
}
//**静态方法,byte数据类型序列化器
static RedisSerializer byteArray() {
return ByteArrayRedisSerializer.INSTANCE;
}
//**检查是此序列化器否能够序列化指定数据类型
default boolean canSerialize(Class> type) {
return ClassUtils.isAssignable(getTargetType(), type);
}
//**此序列化器针对的数据类型,默认object
default Class> getTargetType() {
return Object.class;
}
3.2.ByteArrayRedisSerializer
一个枚举类型,针对byte数据类型;
redis最终保存的就是byte数据类型,所有此类的serialize和deserialize什么都没干,直接返回数据;
3.3.StringRedisSerializer
//**字符集
private final Charset charset;
//**针对不同字符集的StringRedisSerializer
public static final StringRedisSerializer US_ASCII = new StringRedisSerializer(StandardCharsets.US_ASCII);
public static final StringRedisSerializer ISO_8859_1 = new StringRedisSerializer(StandardCharsets.ISO_8859_1);
public static final StringRedisSerializer UTF_8 = new StringRedisSerializer(StandardCharsets.UTF_8);
//**默认为UTF_8字符集
public StringRedisSerializer() {
this(StandardCharsets.UTF_8);
}
//**使用指定的字符集直接把byte转换为string类型
@Override
public String deserialize(@Nullable byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
//**使用指定的字符集直接把string类型转换为byte
@Override
public byte[] serialize(@Nullable String string) {
return (string == null ? null : string.getBytes(charset));
}
//**此序列化器针对的数据类型为string
@Override
public Class> getTargetType() {
return String.class;
}
3.4.GenericToStringSerializer
针对object数据类型;
序列化时使用spring ConversionService/TypeConverter把对象转换为string,然后在把string转换为byte;
反序列化时把byte转换为string,然后使用spring ConversionService/TypeConverter把string转换为对象;
必须指定一个反序列化后的数据类型,反序列化只能生成该数据类型对象;
//**反序列化时,转换后的java数据类型
private final Class type;
//**字符转换为byte时的字符集
private final Charset charset;
//**默认使用DefaultConversionService
private Converter converter = new Converter(new DefaultConversionService());
//**必须指定反序列化后的java数据类型type,反序列化只能生成type数据类型的对象
public GenericToStringSerializer(Class type) {
this(type, StandardCharsets.UTF_8);
}
@Override
public T deserialize(@Nullable byte[] bytes) {
...
//**把byte转换为string
String string = new String(bytes, charset);
//**使用converter把string转换为对象
return converter.convert(string, type);
}
@Override
public byte[] serialize(@Nullable T object) {
...
//**使用converter把对象转换为string
String string = converter.convert(object, String.class);
//**把string转换为byte
return string.getBytes(charset);
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
// TODO: converter不会为空,所以这段做对不会使用到
if (converter == null && beanFactory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory cFB = (ConfigurableBeanFactory) beanFactory;
ConversionService conversionService = cFB.getConversionService();
converter = (conversionService != null ? new Converter(conversionService)
: new Converter(cFB.getTypeConverter()));
}
}
3.5.JdkSerializationRedisSerializer
针对object数据类型;
序列化时直接使用java的ByteArrayOutputStream把对象转换为byte;
反序列化时直接使用java把ByteArrayInputStream把byte转换为对象;
序列化把对象转换为对象的java字节码,可阅读性比较差;
JdkSerializationRedisSerializer
//**序列化转换器
private final Converter serializer;
//**反序列化转换器
private final Converter deserializer;
//**使用SerializingConverter和DeserializingConverter做为默认的序列化和反序列化转换器
public JdkSerializationRedisSerializer() {
this(new SerializingConverter(), new DeserializingConverter());
}
public Object deserialize(@Nullable byte[] bytes) {
...
//**调用反序列化转换器把byte转换为object对象
return deserializer.convert(bytes);
...
}
@Override
public byte[] serialize(@Nullable Object object) {
...
//**调用序列化转换器把byte转换为object对象
return serializer.convert(object);
...
}
序列化
SerializingConverter.java
//**使用DefaultSerializer做为默认的序列化器
public SerializingConverter() {
this.serializer = new DefaultSerializer();
}
@Override
public byte[] convert(Object source) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
...
//**调用DefaultSerializer的serialize方法序列化
this.serializer.serialize(source, byteStream);
return byteStream.toByteArray();
}
@Override
public void serialize(Object object, OutputStream outputStream) throws IOException {
//**必须实现Serializable接口
if (!(object instanceof Serializable)) {
throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +
"but received an object of type [" + object.getClass().getName() + "]");
}
//**调用ObjectOutputStream的writeObject方法
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
objectOutputStream.flush();
}
反序列化同序列化基本一样
3.6.GenericJackson2JsonRedisSerializer/Jackson2JsonRedisSerializer
针对object数据类型;
序列化时使用jackson的ObjectMapper把对象转换为json文本,然后转换为byte;
反序列化时使用jackson的ObjectMapper把byte转换为json文本,然后把json文本转换为对象;
序列化把对象转换为json文本,可阅读性强;
区别
Jackson2JsonRedisSerializer需要使用泛型;
Jackson2JsonRedisSerializer可由调用者自定义ObjectMapper对象;也可使用内置ObjectMapper对象,但没有任务配置;
GenericJackson2JsonRedisSerializer可由调用者自定义ObjectMapper对象;也可使用内置ObjectMapper对象,它初始化了一些配置:
给null值注册了一个类型序列化器;
会将除(String、Double、Integer、Double)外的非常量(non-final)的java类型信息的写入到json文本中;
Jackson2JsonRedisSerializer
//**需要指定泛型类型,反序列时转换为javaType后,在强转为指定的泛型类型
public class Jackson2JsonRedisSerializer implements RedisSerializer {
//**默认使用UTF_8字符集
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
//**java类型映射的jackson类型,反序列化时把json文本转换为javaType的类型
private final JavaType javaType;
//**默认的objectMapper
private ObjectMapper objectMapper = new ObjectMapper();
//**需指定反序列化时转换为的类型
public Jackson2JsonRedisSerializer(Class type) {
this.javaType = getJavaType(type);
}
public Jackson2JsonRedisSerializer(JavaType javaType) {
this.javaType = javaType;
}
//**反序列化
public T deserialize(@Nullable byte[] bytes) throws SerializationException {
//**空值返回null
if (SerializationUtils.isEmpty(bytes)) {
return null;
}
...使用objectMapper把bytes转换为javaType的类型
return (T) this.objectMapper.readValue(bytes, 0, bytes.length, javaType);
...
}
//**序列化
public byte[] serialize(@Nullable Object t) throws SerializationException {
//**null返回空byte数组
if (t == null) {
return SerializationUtils.EMPTY_ARRAY;
}
...使用objectMapper把对象转换为byte数组
return this.objectMapper.writeValueAsBytes(t);
...
}
//**获取java类型映射的jackson类型
protected JavaType getJavaType(Class> clazz) {
return TypeFactory.defaultInstance().constructType(clazz);
}
}
GenericJackson2JsonRedisSerializer
public class GenericJackson2JsonRedisSerializer implements RedisSerializer {
//**默认为@class
public GenericJackson2JsonRedisSerializer() {
this((String) null);
}
//**设置默认的ObjectMapper,并初始化
//**classPropertyTypeName:jackon会将java类型信息的写入到json文本中,classPropertyTypeName指定java类型信息写入的格式
public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName) {
//**默认的ObjectMapper
this(new ObjectMapper());
//**给null值注册了一个类型序列化器
registerNullValueSerializer(mapper, classPropertyTypeName);
if (StringUtils.hasText(classPropertyTypeName)) {
//**指定了classPropertyTypeName为java类型信息写入的格式
mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, classPropertyTypeName);
} else {
//**指定了PROPERTY为java类型信息写入的格式,默认为@class
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
}
}
//**序列化
public byte[] serialize(@Nullable Object source) throws SerializationException {
//**null返回空byte数组
if (source == null) {
return SerializationUtils.EMPTY_ARRAY;
}
...使用objectMapper把对象转换为byte数组
return mapper.writeValueAsBytes(source);
...
}
//**反序列化,默认转换为object对象
@Override
public Object deserialize(@Nullable byte[] source) throws SerializationException {
return deserialize(source, Object.class);
}
//**反序列化
@Nullable
public T deserialize(@Nullable byte[] source, Class type) throws SerializationException {
//**空值返回null
if (SerializationUtils.isEmpty(source)) {
return null;
}
...使用objectMapper把bytes转换为type类型
return mapper.readValue(source, type);
...
}
//**空值类型序列化器
private static class NullValueSerializer extends StdSerializer {
private static final long serialVersionUID = 1999052150548658808L;
private final String classIdentifier;
//**指定java类型信息写入格式,默认为@class
NullValueSerializer(@Nullable String classIdentifier) {
super(NullValue.class);
this.classIdentifier = StringUtils.hasText(classIdentifier) ? classIdentifier : "@class";
}
//**序列化
public void serialize(NullValue value, JsonGenerator jgen, SerializerProvider provider) throwsIOException {
jgen.writeStartObject();
//**写入空值的类型信息(@class, NullValue)
jgen.writeStringField(classIdentifier, NullValue.class.getName());
jgen.writeEndObject();
}
}
}
3.7.GenericFastJsonRedisSerializer/FastJsonRedisSerializer
针对object数据类型,是fastjson.jar里面实现的RedisSerializer;
序列化时使用fastjson的JSON.toJSONBytes把对象转换为json文本,然后转换为byte;
反序列化时把byte转换为json文本,然后使用JSON.parseObject把json文本转换为对象;
序列化把对象转换为json文本,可阅读性强;
区别
FastJsonRedisSerializer需要使用泛型,序列化的反序列化泛型指定的类型;
GenericFastJsonRedisSerializer序列化和反序列化object类型;
FastJsonRedisSerializer
//**需要指定泛型类型,反序列时转换为type后,在强转为指定的泛型类型
public class FastJsonRedisSerializer implements RedisSerializer {
//**序列化
public byte[] serialize(T t) throws SerializationException {
//**null返回空byte数组
if (t == null) {
return new byte[0];
}
...使用JSON.toJSONBytes把对象转换为byte数组
return JSON.toJSONBytes(t, fastJsonConfig.getSerializeConfig(), fastJsonConfig.getSerializerFeatures());
...
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
//**空值返回null
if (bytes == null || bytes.length == 0) {
return null;
}
...使用JSON.parseObject把bytes转换为type类型
return (T) JSON.parseObject(bytes, type, fastJsonConfig.getFeatures());
...
}
}
GenericFastJsonRedisSerializer
public class GenericFastJsonRedisSerializer implements RedisSerializer {
//**序列化
public byte[] serialize(Object object) throws SerializationException {
//**null返回空byte数组
if (object == null) {
return new byte[0];
}
...使用JSON.toJSONBytes把对象转换为byte数组
return JSON.toJSONBytes(object, SerializerFeature.WriteClassName);
...
}
//**反序列化
public Object deserialize(byte[] bytes) throws SerializationException {
//**空值返回null
if (bytes == null || bytes.length == 0) {
return null;
}
...先把bytes转换为string,然后使用JSON.parseObject把string转换为obejct类型
return JSON.parseObject(new String(bytes, IOUtils.UTF8), Object.class, defaultRedisConfig);
...
}
}
3.8.OxmSerializer
针对object数据类型;
序列化时使用spring oxm的Marshaller把对象转换为xml文本,然后转换为byte;
反序列化时使用spring oxm的Unmarshaller把byte转换为xml文本,然后把xml文本转换为对象;
序列化把对象转换为xml文本,可阅读性强;
//**实现了InitializingBean接口,spring容器启用时,会调用afterPropertiesSet方法进行一些初始化,同类型还有 @PostConstruct
public class OxmSerializer implements InitializingBean, RedisSerializer {
//**初始化,验证marshaller/unmarshaller不能为空,marshaller/unmarshaller必须传入,没有默认值
@Override
public void afterPropertiesSet() {
Assert.state(marshaller != null, "non-null marshaller required");
Assert.state(unmarshaller != null, "non-null unmarshaller required");
}
//**反序列化
public Object deserialize(@Nullable byte[] bytes) throws SerializationException {
//**空值返回null
if (SerializationUtils.isEmpty(bytes)) {
return null;
}
...使用unmarshaller把bytes转换为type类型
return unmarshaller.unmarshal(new StreamSource(new ByteArrayInputStream(bytes)));
...
}
//**序列化
public byte[] serialize(@Nullable Object t) throws SerializationException {
//**null返回空byte数组
if (t == null) {
return SerializationUtils.EMPTY_ARRAY;
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
StreamResult result = new StreamResult(stream);
...使用marshaller把对象转换为xml文本,然后写入ByteArrayOutputStream
marshaller.marshal(t, result);
...
//**把ByteArrayOutputStream转换为byte数组
return stream.toByteArray();
}
}