Java序列化是在JDK 1.1中引入的,是Java内核的重要特性之一。如果希望一个类对象是可序列化的,所要做的就是实现Serializable接口。Serializable是一个标记接口,不需要实现任何字段和方法。这就像是一种选择性加入的处理,通过它可以使类对象成为可序列化的对象。序列化处理是通过ObjectInputStream和ObjectOutputStream实现的,因此我们所要做的是基于它们进行一层封装,要么将其保存为文件,要么将其通过网络发送。我们来看一个简单的序列化示例。
步骤01 定义AyUser对象,并实现Serializable接口,具体代码如下所示:
步骤02 自定义序列化接口ISerializer,具体代码如下所示:
步骤03 实现序列化接口ISerializer,同时实现serialize、deserialize、serializeToFile和deserializeFromFile方法,具体代码如下所示:
步骤04 开发测试程序,具体代码如下所示:
运行main方法,将在控制台打印如下信息,同时可以在项目下找到tmp.out文件。
打开项目下的tmp.out文件,文件内容如图4-1所示。
图4-1 tmp.out文件内容
这里对tpm.out文件进行简单分析,具体如下:
第一部分:序列化文件头
AC ED:STREAM_MAGIC,声明使用了序列化协议。
00 05:STREAM_VERSION,序列化协议版本。
73:TC_OBJECT,声明这是一个新的对象。
第二部分:序列化的类的描述
72:TC_CLASSDESC,声明这里开始一个新Class。
00 1D:Class名字的长度为29。
63 6F 6D 2E … 73 65 72:AyUser,Class类名。
62 AE F9 09 05 48 6F FB:SerialVersionUID,序列化ID,如果没有指定,就会由算法随机生成一个8字节的ID。
02:标记号,该值声明该对象支持序列化。
00 02:该类所包含的域个数。
第三部分:对象中各个属性的描述
4C:域类型:Long。
00 02:域名字的长度。
69 64 74 00 10 4C 6A:id,域名字描述。
第四部分:对象的父类信息描述
Serializable没有父类,如果有,就和第二部分的描述相同。
78:TC_ENDBLOCKDATA,对象块结束的标志。
70:TC_NULL,说明没有其他超类的标志。
第五部分:对象属性的实际值
这里只是简单分析JDK默认序列化协议,读者可以在网络上参考更多资料。
Java默认的序列化机制缺点很明显:
(1)只支持Java语言,不支持其他语言。
(2)性能差,序列化后的码流大,对于引用过深的对象序列化容易引起OOM异常。
XML序列化使用标签表示数据,可读性高。但是序列化后码流较大,性能不高,适用于性能不高且QPS较低的企业级内部系统之间数据交换的场景。XML具有语言无关性,可用于异构系统间的数据交换协议。XML序列化和反序列化实现方式有多种,比如XStream和Java自带的XML序列化和反序列化方式等。我们主要讲解Java自带的XML序列化和反序列化方式,其他的方式读者可自己查资料学习。
Java自带的XML序列化和反序列化主要使用XMLEncoder和XMLDecoder类实现相应的功能,具体实例如下所示:
上述代码开发完成之后,运行main函数,将可以在控制台看到如下打印信息:
id :1 name :ay
同时,在项目的目录下会生成ayUser.xml文件,文件内容如下所示:
下面我们简单封装XML序列化类XMLSerializer供读者参考,具体代码如下所示:
JSON(JavaScript Object Notation,JS对象简谱)是一种轻量级的数据交换格式。JSON可以支持任何数据类型,例如字符串、数字、对象、数组等。相对于XML,JSON码流更小,而且还保留了XML可读性好的优势。
JSON序列化常用的开源工具有Fastjson(阿里巴巴开源)、Jackson和Google开发的GSON。从性能角度来看,Jackson和Fastjson比GSON的性能好。从稳定性来看,Jackson、GSON相对Fastjson稳定性更好。
接下来,我们重点介绍Fastjson序列化框架,该框架的主要优点有:
使用Fastjson进行序列化和反序列化非常简单,具体步骤如下所示。
步骤01 添加Fastjson依赖包,具体代码如下所示:
步骤02 开发序列化类JsonSerializer,简单封装序列化和反序列化接口:
Google Protocol Buffer(简称ProtoBuf)是一种轻便高效的结构化数据存储格式,与平台无关、与语言无关、可扩展,可用于通信协议和数据存储等领域。
ProtoBuf高性能解析且码流小,非常适合性能要求高的RPC调用。但是使用ProtoBuf需要编写.proto IDL文件,开发工作量稍大,且需要额外学习Proto IDL特有的语法。
下面我们开始学习如何使用ProtoBuf序列化框架实现对象的序列化和反序列化,具体步骤如下:
步骤01 下载ProtoBuf安装包,例如protobuf-all-3.6.1.tar。
步骤02 在终端执行解压命令:
### 解压protobuf-all-3.6.1.tar tar zxvf protobuf-all-3.6.1.tar
步骤03 在解压后的目录protobuf-3.6.1下执行命令:
步骤04 执行protoc --version命令检查是否安装成功,如果输出如下信息,就代表ProtoBuf安装成功。
### 安装成功输出结果 libprotoc 3.6.1
ProtoBuf安装成功之后,紧接着学习如何使用ProtoBuf,具体步骤如下所示。
步骤01 创建用户类AyUser,具体代码如下所示:
步骤02 编写AyUser.proto文件,具体代码如下所示:
表4-1 ProtoBuf字段支持的类型汇总
步骤03 执行如下命令,生成相关的序列化工具类:
该命令需要在项目的java目录下执行。
我们还可以在终端输入protoc --help命令查看protoc命令更多信息,具体代码如下所示:
步骤04 开发代码,将AyUser对象进行序列化和反序列化:
代码开发完成之后,运行main方法,便可以在控制台打印相关的信息。至此,使用ProtoBuf进行对象序列化和反序列化已完成,更多ProtoBuf相关的内容,读者可自主学习。