为什么需要序列化
什么情况下需要序列化
序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protostuff、FST(不支持跨语言)。
Java 序列化
注意: JAVA序列化中常见的问题
问题一:static 属性不能被序列化
原因:序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。
问题二:Transient 属性不会被序列化
java 的 transient 关键字的作用是需要实现 Serilizable 接口,将不需要序列化的属性前添加关键字 transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
问题三:序列化版本号serialVersionUID
所有实现序列化的对象都必须要有个版本号,这个版本号可以由我们自己定义,当我们没定义的时候JDK工具会按照我们对象的属性生成一个对应的版本号。使用JDK生成的 serialVersionUID,只要对象有一丁点改变serialVersionUID就会随着变更。因此建议自己手动定义该版本号。
redis序列化方式对比:
redis 的默认方式是 JdkSerializationRedisSerializer。
JdkSerializationRedisSerializer:使用JDK提供的序列化功能。优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
Jackson2JsonRedisSerializer:使用Jackson库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。通过查看源代码,发现其只在反序列化过程中用到了类型信息。
问题:使用默认的JDK序列化方式,在RDM工具中查看k-v值时会出现“乱码”,不方便查看。
解决:自定义系列化方式,使用Jackson2JsonRedisSerializer
Redis 序列化
当你用Redis的key和value时,value对于redis来讲就是个byte array。你要自己负责把你的数据结构转换成byte array,等读取时再读出来。
一个特例是字符串,因为字符串自己几乎就已经是byte array了,所以不需要自己处理。
Spring 的 redisTemplate 默认会使用 java serialization 做序列化。你也可以用 StringRedisTemplate,那么你 set 的所有数据都会被 toString 一下再存到 redis 里。但这个 toString 不一定能反解析的回来。如果使用 java 原生序列化方式,可能会有远程代码执行问题,因此建议使用其他序列化方式代替。