3.springboot-reids 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();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章