序列化
在前面我们已经讲了,Java分布式通讯基于Socket,使用Socket通讯必须指定以下关键点:
IP
Port
通讯协议
其中很多通讯协议通常与RPC框架有关联,但是比较通用的,比如HTTP协议,这里就不再过多解释。关于通讯协议的部分,将会结合着RPC框架来进行讲解。本篇文章将会简单描述几种常用的序列化的使用方式,着重比较他们之间的序列化与反序列化效率。
通讯协议中不仅包含协议的内容,更是包含了我们通讯的数据。我们的数据在传输之前,位于Java代码中都是以JavaObject的形式表示的,因此这些数据在网络传输时,不可避免序列化、反序列化的过程。恰当的序列化方式不仅可以提高系统的性能,更是可以提高系统的安全性、通用性、强壮性,让系统易于调试和拓展。
常见的序列化机制
序列化方式,时间排序 | 优点 | 缺点 | 主要应用 |
---|---|---|---|
Serializable | 序列化结果大、传输效率低、不能跨语言对接 | RMI | |
XML | 通俗易懂、跨语言 | 序列化结果大、冗余标签多、传输效率低 | WebService(SOAP) |
JSON | 通俗易懂、比起xml更精简,与js兼容好 | 序列化结果仍然很大、性能较低 | HTTP Rest |
Hessian | 跨语言、紧凑的二进制协议、序列化速度快 | 序列化后的结果很大,大于Java序列化、可读性差 | |
MessagePack | 兼容 json 的数据格式、但是比JSON跟节省空间、支持多语言 | 序列化时间长大约是JSON的两倍 | |
Protocol Buffer | 吊打上面几个 | 需要预编译、安装 比较麻烦 | |
Apache Thrift | 与Protocol Buffers差不多、序列化时间要比Protocol Buffers短、反序列化时间要比PB长 | ||
Apache Avro | 配置复杂 | ||
Kryo | 针对Java的序列化系统 | 不跨语言 | |
FST | 针对Java的序列化系统 | 不跨语言 |
Serializable
Serializable 是Java自带的序列化方式,速度慢,不跨语言,唯一的优点可能就是Java自带,不需要引入任何第三方扩展。Serializable
的序列化与发序列化需要借助ObjectInputStream
和ObjectOutputStream
,下面是代码演示:
serialVersionUID
凡是实现Serializable
接口的类,都需要声明 serialVersionUID
来标识序列化版本号。当使用版本号1进行序列化时,只能通过相同的版本号的类进行反序列化,否则就会抛出java.io.InvalidClassException
。以此保证序列化类型与反序列化类型是同一类型。
如果未指定serialiVersionUID
,Java 编译器会自动对类进行摘要算法生成一个serialVersionUID
,所以只要目标Java类有任何变动,得到的结果就会截然不同。
静态变量序列化
序列化并不保存静态变量的状态,所以序列化时静态变量 a
的值为2,那么反序列化时a的值不见的就是2,他的值仍然是 类.a
的值
transient 关键字
如果想要某个属性不参与序列化,可以给这个属性加上transient
关键字。
父子类序列化问题
如果父类没有实现序列化接口、子类实现了序列化接口,那么父类中的属性无法参与序列化
如果父类实现了序列化接口,子类没有实现,子类继承父类,所以父子类属性都会参与序列化
序列化的存储规则
假设将Person p
对象序列化写入到文件p.bak
中,第一次假设耗费15ms的时间写入到了磁盘中,那么第二次写入同样的p对象,此时Java发现磁盘中已经存在此序列化文件,那么Java不会覆盖文件,而是在文件尾部添加了5个字节的引用关系,从而提高了重复对象的写入效率。下面是代码示例:
深度克隆
使用Java Serializable 还可以实现深克隆,只需要保证要克隆的对象以及属性都实现了Serializable接口即可,复制出的对象与原有对象是两个对象。代码这里不再演示。
JSON
JSON序列化方式是Java应用程序中最为常用的序列化方式,与Javascript有较好的兼容性,最典型的就是用在Rest架构中。JSON序列化方式可以使用的第三方jar有很多,比如最常用的,也是SpringBoot中自带的JSON序列化方式:Jackson,以及Alibaba的用起来很方便的Fastjson,以及Android中常用的Gson。下面是三种工具的使用方式。
Jackson
感觉Jackson用起来不是很方便,使用Jackson需要创建一些前置对象,下面是他最简单的序列化反序列化方式:
Fastjson
Fastjson是开发中公司用的较多的JSON框架,用起来比较方便,而且速度也很快,下面是他的示例代码:
Gson
Gson是Google的一款JSON序列化框架,使用起来也是比较方便的,笔者是很久之前还在学习Android的时候接触的,算是接触的最早的JSON框架,但是对其使用并不是很了解:
Protocol Buffer
Protocal Buffer是Google提供的一种数据序列化协议,是一种轻便高效的结构化数据存储格式,适合作为数据存储或者RPC数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
实现一个Protocol Buffer较为复杂,这里使用百度提供的工具包 jprotobuf
:
代码演示:
protobuf性能高有两个主要原因
针对字节数据进行了压缩,所以生成的数据较小,所以传输效率较高
针对数据进行了缓存
Hessian
Hessian序列化的方式同样是跨语言的,是一种二进制的序列化方式。值得一提的是,Hessian序列化的速度很快,但是序列化的结果所占的字节数却很大。
最后更新于