4.2 常用序列化框架
4.2.1 Java默认序列化
Java序列化是在JDK 1.1中引入的,是Java内核的重要特性之一。如果希望一个类对象是可序列化的,所要做的就是实现Serializable接口。Serializable是一个标记接口,不需要实现任何字段和方法。这就像是一种选择性加入的处理,通过它可以使类对象成为可序列化的对象。序列化处理是通过ObjectInputStream和ObjectOutputStream实现的,因此我们所要做的是基于它们进行一层封装,要么将其保存为文件,要么将其通过网络发送。我们来看一个简单的序列化示例。
定义AyUser对象,并实现Serializable接口,具体代码如下所示:
自定义序列化接口ISerializer,具体代码如下所示:
实现序列化接口ISerializer,同时实现serialize、deserialize、serializeToFile和deserializeFromFile方法,具体代码如下所示:
开发测试程序,具体代码如下所示:
运行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异常。
4.2.2 XML序列化框架
XML序列化使用标签表示数据,可读性高。但是序列化后码流较大,性能不高,适用于性能不高且QPS较低的企业级内部系统之间数据交换的场景。XML具有语言无关性,可用于异构系统间的数据交换协议。XML序列化和反序列化实现方式有多种,比如XStream和Java自带的XML序列化和反序列化方式等。我们主要讲解Java自带的XML序列化和反序列化方式,其他的方式读者可自己查资料学习。
Java自带的XML序列化和反序列化主要使用XMLEncoder和XMLDecoder类实现相应的功能,具体实例如下所示:
上述代码开发完成之后,运行main函数,将可以在控制台看到如下打印信息:
id :1 name :ay
同时,在项目的目录下会生成ayUser.xml文件,文件内容如下所示:
下面我们简单封装XML序列化类XMLSerializer供读者参考,具体代码如下所示:
4.2.3 JSON序列化框架
JSON(JavaScript Object Notation,JS对象简谱)是一种轻量级的数据交换格式。JSON可以支持任何数据类型,例如字符串、数字、对象、数组等。相对于XML,JSON码流更小,而且还保留了XML可读性好的优势。
JSON序列化常用的开源工具有Fastjson(阿里巴巴开源)、Jackson和Google开发的GSON。从性能角度来看,Jackson和Fastjson比GSON的性能好。从稳定性来看,Jackson、GSON相对Fastjson稳定性更好。
接下来,我们重点介绍Fastjson序列化框架,该框架的主要优点有:
- Fastjson具有极快的性能。
- 功能强大,完全支持Java Bean、集合、Map、日期、Enum,同时支持泛型、支持自省等。
- 无依赖,能够直接运行在Java SE 5.0以上版本。
- 易用的API操作。
使用Fastjson进行序列化和反序列化非常简单,具体步骤如下所示。
添加Fastjson依赖包,具体代码如下所示:
开发序列化类JsonSerializer,简单封装序列化和反序列化接口:
4.2.4 ProtoBuf序列化框架
Google Protocol Buffer(简称ProtoBuf)是一种轻便高效的结构化数据存储格式,与平台无关、与语言无关、可扩展,可用于通信协议和数据存储等领域。
ProtoBuf高性能解析且码流小,非常适合性能要求高的RPC调用。但是使用ProtoBuf需要编写.proto IDL文件,开发工作量稍大,且需要额外学习Proto IDL特有的语法。
下面我们开始学习如何使用ProtoBuf序列化框架实现对象的序列化和反序列化,具体步骤如下:
下载ProtoBuf安装包,例如protobuf-all-3.6.1.tar。
在终端执行解压命令:
### 解压protobuf-all-3.6.1.tar tar zxvf protobuf-all-3.6.1.tar
在解压后的目录protobuf-3.6.1下执行命令:
执行protoc --version命令检查是否安装成功,如果输出如下信息,就代表ProtoBuf安装成功。
### 安装成功输出结果 libprotoc 3.6.1
ProtoBuf安装成功之后,紧接着学习如何使用ProtoBuf,具体步骤如下所示。
创建用户类AyUser,具体代码如下所示:
编写AyUser.proto文件,具体代码如下所示:
- syntax= "proto3":指定正在使用Proto 3语法,如果没有指定编译器,就默认使用Proto 2。
- option java_package:表示自动生成代码时,将Java代码放入指定的package中。
- java_outer_classname:表示生成的Java类的名称。
- message:表示声明一个“类”,类似Java中的class。message中可以内嵌message,就像Java的内部类一样。一个message可以包含多个字段。ProtoBuf字段支持的数据类型如表4-1所示。
表4-1 ProtoBuf字段支持的类型汇总
执行如下命令,生成相关的序列化工具类:
- java_out指定生成Java代码保存的目录,后面紧跟.proto文件的路径。
注 意
该命令需要在项目的java目录下执行。
我们还可以在终端输入protoc --help命令查看protoc命令更多信息,具体代码如下所示:
开发代码,将AyUser对象进行序列化和反序列化:
代码开发完成之后,运行main方法,便可以在控制台打印相关的信息。至此,使用ProtoBuf进行对象序列化和反序列化已完成,更多ProtoBuf相关的内容,读者可自主学习。