序列化-一个老家伙的咸鱼翻身Java对象XMLJSON反序列化

32次阅读

共计 2589 个字符,预计需要花费 7 分钟才能阅读完成。

转自:码农翻身(微信号:coderising)

1、寒冬的蛰伏

这里的工作很繁忙,一年 365 天,一天 24 小时几乎不停工。

但是我却是一个闲人,因为我做的工作最近用的人太少了,经常被冷落在一边。

大多数时候,我只能羡慕的看着线程、反射、注解、集合、泛型这些明星员工在那里忙忙碌碌,听着他们充满激情的的大声说笑。

他们都叫我序列化,想想也是,我的工作就是把一个 Java 对象变成二进制的字节流,或者反过来把字节流变成 Java 对象,这有什么意思?

当大家需要一个 Java 对象的时候,直接 new 出来不就得了,对象不用了自然有令人胆战心惊的垃圾回收去处理。

但是存在即合理,在 JDk1.1 的时代,我就已经存在了。当时人们的思想很超前:网络就是计算机。一个个 Java 对象应该可以在网络中到处旅行:从一个机器出发时,就变成二进制字节流,顺着网络跨过千山万水,到达另外一台机器,在那里摇身一变,恢复成 Java 对象,在那里继续运算。


既然可以以二进制方式在网络中漫游,那自然也可以把这些字节流存到硬盘中,当 JVM 停机,整个世界坍塌以后,线程,反射,注解都不复存在了,而我的字节流还会在硬盘上默默等待,等待下一次 JVM 的重生,把对象恢复。

所以我觉得我的工作也很有价值,从某种意义上来讲,我可以让 Java 对象跨越时间和空间而永生!

这种永生是有代价的,首先你必须得用 Java,这是废话,因为我只是 java 对象序列化。

虽然那二进制字节流的格式是公开的,你可以用任何语言 (C,C++,Python…) 去解析读取,但是解析以后又有什么用处呢?那些字节流中会告知你这是哪个类的数据,字段的类型和值,但是如果你没有相对应的 Java 类,还是无法构建出 Java 对象出来。
其次,做序列化双方的类必须得一致,要不然肯定出乱子。

大部分人都不知道在上个世纪末和本世纪初,我还是随着 J2EE 火了一阵,当时 J2EE 中有个叫 RMI 东西,其实就是 Java RPC。由于我卓越的工作,开发人员用可以轻松的调用远程服务器上的 Java 方法,就相当于调用本地方法一样,很方便。

可惜的是这个 RMI 只能用在 Java 环境中,对于服务器来说这根本不是问题,但是当时 Web 应用正在兴起,一个浏览器中是很难有 Java 环境的,所以 RMI 很快就没落了,我也随之被打入冷宫,我也只好蛰伏下来,等待机会。

序列化生成代码

2、XML 和 JSON 的挑战

后来我们这里来了一个叫 XML 的小伙子,很受大家的欢迎,都喜欢把 Java 对象序列化的工作交给他去做。

我不能坐以待毙,我仔细的观察了几天以后,终于发现这个家伙有个大缺点:太复杂了!

对于我的 Java 序列化,大部分情况下你只需要让你的类实现 Serializable 接口,我就可以接管后续的所有工作。不用你操心了。

可是用 XML, 你还得写一堆代码把一个类中的各个字段和他们的值变成 XML 标签 / 属性 / 值 才行。当用来表示对象的 XML 字符串漫游到另外一个机器上,还得有一堆代码把 XML 变成对象。

我嘲笑 XML 说:“小伙子,你这也太麻烦了吧,人类的时间多宝贵,为了用 XML 做序列化,代价好高嗷!”

“老家伙,没你想的那么复杂,你可能不知道,我们有些类库能自动帮助把对象变成 XML”他毫不示弱。

“不要忘了”小伙子补充道“我们 XML 可是语言中立的,在这里是 Java 对象,到了客户端 什么语言都行,Java/C/Python/Ruby… 都没问题,甚至浏览器里的 Javascript 都能处理,这一点你不行了吧?”

这家伙戳到了我的痛处,在浏览器中我的确需要一个 Java 环境才行运行,唉,真是成也 Java , 败也 Java。

我说:“我知道你是语言无关的,但是你注意到没有,你的 XML 标签冗余太多,真正的数据很少。比如有个 Person 类,有两个字段 name 和 address, 用你的 XML 做序列化就变成了这个样子

<person>
    <name>abc</name>
    <address>xyz</address>
</person>

,这在网络上传输起来绝对是一种浪费!我的 java 字节流就不一样了,二进制的,非常紧凑,一点都不浪费!“

XML 小伙子沉默了,小样,我也抓住了你的痛点。

过了两天,这个小伙子又带来了一个叫 JSON 的小弟,他得意洋洋的向我炫耀:用了 JSON 以后,数据精简多了,不信你看:{“name”:“abc”,“address”:“xyz”},现在我们不但语言中立,还很精简,老家伙,这下你无话可说了吧。


我认栽,但是让 XML 也没高兴多久,让他没有想到的是,Web 时代 JSON 和 Javascript 是一对绝配,联手统治了浏览器。连 XML 自己都快没饭吃了。

3、新协议的崛起

其实我一直觉得我的二进制序列化方式能减少存储空间,方便网络传输,只是我的硬伤是无法跨越语言。

不行,我不能一直守着 Java 这一亩三分地了,必须扩展支持多语言,这样才能脱离 Java 环境。

有人说:计算机的所有问题都可以通过增加一个中间层来解决。我是不是也可以搞个中间层出来?

让这个中间层来定义 / 描述消息的格式,然后再弄一个小翻译器(不,叫编译器显的更加高大上),把这个程序员自定义的消息格式转换成各种语言的实现,例如 java, python, c++ 等等。

在转换好的语言实现里边,自动包含了要被序列化的类的定义,以及实现序列化和反序列化的代码,当然序列化以后的数据是二进制的。

等到二进制的字节流通过网络传输到另外一台机器,就可以反序列化为各种语言(例如 Python)的对象了,当然必须是同一个消息格式产生的 Python 类。


不仅仅是 Python, C++, Go, C# , 甚至 Javascript 都可以用!

是不是很爽?既语言中立,又采用二进制传输,体积小,解析快,完美的综合了各种优点!

唯一的额外工作是需要把消息格式的定义编译成各种语言的实现,为了能支持多语言,这也是没办法的事情。

我得意的把新方案给 XML 和 JSON 这两个家伙看了,从表情来看,就知道他俩如临大敌了。

我也把方案提交给了我们服务器世界的老大,他大为赞赏,决定先在部分场景下用起来,例如对象存入缓存的时候需要序列化,以前用 json, 占用空间很大,改用了我的新方案以后,不但减少了空间使用,还提升了读写的效率,效果不错。

我成功地扳回了一局,现在找我用新方案来做序列化的人越来越多了,但是最终鹿死谁手还很难说,最有可能的情况是,各种方案混合使用,即使是这样,我也很满足了。

正文完
 0