3.springboot redis序列化器

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<Object> java() {
	return java(null);
}

//**静态方法,java格式序列化器
static RedisSerializer<Object> java(@Nullable ClassLoader classLoader) {
	return new JdkSerializationRedisSerializer(classLoader);
}

//**静态方法,json格式序列化器
static RedisSerializer<Object> json() {
	return new GenericJackson2JsonRedisSerializer();
}

//**静态方法,string数据类型序列化器
static RedisSerializer<String> string() {
	return StringRedisSerializer.UTF_8;
}

//**静态方法,byte数据类型序列化器
static RedisSerializer<byte[]> 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
  • 针对string数据类型
//**字符集
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<T> type;

//**字符转换为byte时的字符集
private final Charset charset;

//**默认使用DefaultConversionService
private Converter converter = new Converter(new DefaultConversionService());

//**必须指定反序列化后的java数据类型type,反序列化只能生成type数据类型的对象
public GenericToStringSerializer(Class<T> 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<Object, byte[]> serializer;
    //**反序列化转换器
    private final Converter<byte[], Object> 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();
      }
      
      • DefaultSerializer
      @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<T> implements RedisSerializer<T> {
    //**默认使用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<T> 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<Object> {

	//**默认为@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> T deserialize(@Nullable byte[] source, Class<T> type) throws SerializationException {
        //**空值返回null
		if (SerializationUtils.isEmpty(source)) {
			return null;
		}

		...使用objectMapper把bytes转换为type类型
		return mapper.readValue(source, type);
		...
	}

	//**空值类型序列化器
	private static class NullValueSerializer extends StdSerializer<NullValue> {

		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<T> implements RedisSerializer<T> {
    
    //**序列化
    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<Object> {
    
    //**序列化
    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<Object> {

    //**初始化,验证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();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值