序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。 (推荐学习:Redis视频教程)
通过上面我想你已经知道了凡是需要进行“跨平台存储”和”网络传输”的数据,都需要进行序列化。
本质上存储和网络传输 都需要经过 把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台才可以通过字节信息解析还原对象信息。
redis序列化方式对比:
redis的默认方式是JdkSerializationRedisSerializer
JdkSerializationRedisSerializer: 使用JDK提供的序列化功能。
优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
Jackson2JsonRedisSerializer: 使用Jackson库将对象序列化为JSON字符串。
优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。
但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息。
问题:使用默认的JDK序列化方式,在RDM工具中查看k-v值时会出现“乱码”,不方便查看。
解决:自定义系列化方式,使用Jackson2JsonRedisSerializer
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
private static final String STANDARD_PATTERN = "yyyy/MM/dd HH:mm:ss";
private static final String DATE_PATTERN = "yyyy/MM/dd";
private static final String TIME_PATTERN = "HH:mm:ss";
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
this.registerLocalDateTime(objectMapper);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
template.setConnectionFactory(connectionFactory);
// key采用String的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
/**
* 处理时间类型
*
* @param objectMapper
*/
private void registerLocalDateTime(ObjectMapper objectMapper) {
// 设置java.util.Date时间类的序列化以及反序列化的格式
objectMapper.setDateFormat(new SimpleDateFormat(STANDARD_PATTERN));
JavaTimeModule timeModule = new JavaTimeModule();
// LocalDateTime
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(STANDARD_PATTERN);
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
// LocalDate
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
// LocalTime
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN);
timeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
timeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
objectMapper.registerModule(timeModule);
}