序列化: 一個老傢伙的鹹魚翻身(Java物件、XML、JSON、反序列化)

書寫人生發表於2019-09-08
原文連結: https://mp.weixin.qq.com/s/ybpdxx2lvZNNqaoXHG24Zg

轉自:碼農翻身(微訊號: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, 佔用空間很大, 改用了我的新方案以後, 不但減少了空間使用, 還提升了讀寫的效率, 效果不錯。

我成功地扳回了一局,現在找我用新方案來做序列化的人越來越多了, 但是最終鹿死誰手還很難說,最有可能的情況是,各種方案混合使用, 即使是這樣,我也很滿足了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947338/viewspace-2656386/,如需轉載,請註明出處,否則將追究法律責任。

相關文章