Hessian是一個輕量級的Web服務實現工具,它采用的是二進制協議,因此很適合發送二進制數據。它的一個基本原理就是把遠程服務對象以二進制的方式進行發送和接收。由二進制引發的問題:
1、傳輸對象必須序列化
假如User類是醬紫的:public class User {} 而不是醬紫的:public class User implements java.io.Serializable {} 那么就會報錯: java.lang.IllegalStateException: Serialized class com.tiantian.po.User must implement java.io.Serializable at com.caucho.hessian.io.SerializerFactory.getDefaultSerializer(SerializerFactory.java:340) ……
這個錯誤是在客戶端hessianClient報的錯,因為客戶端要調用遠程的hessian服務,傳輸對象必須序列化才可以
2、傳輸對象的包路徑,名稱必須一致
剛開始使用Hessian的時候,就覺得很奇怪,兩個不同的項目,在傳遞一個實體類作為參數時,是如何對接的?比如項目A,B,A作為服務端,B作為客戶端,A有一個添加用戶的方法,需要傳遞一個用戶實體類的參數,那B作為調用端,改怎么傳遞呢?實體類名稱一樣就行了嗎?其實不然,還必須保證實體類的包路徑一樣,否則會報錯,為啥?比如上一篇中的兩個項目,如果把hessianClient中的實體類User的包路徑由com.tiantian.po.User改為com.tiantian.po1.User,再運行,則會如下錯:
警告: Hessian/Burlap: 'com.tiantian.po1.User' is an unknown class in WebappClassLoader context: /hessianServer delegate: false repositories: /WEB-INF/classes/ ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@c79809 : java.lang.ClassNotFoundException: com.tiantian.po1.User
就是找不到com.tiantian.po1.User這個類,這個錯誤是在服務端也就是hessianServer所在項目報的錯,因為服務端定義的是po而不是po1,所以客戶端傳遞這個參數過來,我服務端不認識,沒這東西。這就引出什么是序列化,為啥要有序列化這東西了
3、Hessian提供的接口放置的位置
1)、服務端和客戶端的hessian包路徑最好都一樣,統一嘛
2)、需要開放hessian功能的接口copy一個單獨放置在hessian包下(有多少就copy多少),不要把整個比如com.cin.service.IUser整個包給配置在hessian.xml,因為醬紫會把這個包的所有接口都給暴露了,醬紫不好,應該是有一個統一對外的hessian包,里面放置有需要提供的接口
4、序列化
自己的理解:序列化就是一種把對象的狀態轉換成為一組byte的過程,然后這組byte可以在互聯網上傳輸(比如用於Hessian)、保存到數據庫(硬盤);反序列化就是你懂的,反過來嘛,把這組byte數據恢復出來,並據此重構這個對象,那這兩個對象就是一模一樣的了。所以這就解釋了上面的傳輸對象的名稱、包名要一樣,否則會有錯,因為當B傳輸了com.tiantian.po1.User類過去的時候,通過剛才講的,
- 他會被序列化成為一組byte(假設序列化后的格式如下,肯定是以二進制的方式啦:AAA111BBB),然后這組byte就可以在互聯網上傳輸了(我們知道,Java中,一切都是對象,在分布式環境中經常需要將Object從這一端網絡或設備傳遞到另一端。這就需要有一種可以在兩端傳輸數據的協議。Java序列化機制就是為了解決這個問題而產生。),好,走你,……,走到了A項目那里的時候,按道理,通過反序列化之后可以重建com.tiantian.po1.User類的
- 此時1中重建的po1.User就被當成參數類傳進A中對應的方法里,但是問題來了,A中對應的方法要求的參數是com.tiantian.po.User而不是com.tiantian.po1.User,因此就拋出了上面的錯誤
卧槽,尼瑪,我勒個去,馬勒戈壁,終於解開了困擾我很久的一個問題了,從此春暖花開,柳暗花明了……啊哈,貌似這是Java程序猿必須要掌握的基本只是把,傻X。
到此,序列化算是告一段落了,簡單明白Hessian之間的對象傳輸是怎么一回事了,當然具體怎么writeObject和readObject,就得去研究Hessian源碼了,目前功力尚淺,不足以研究,日后再說。
延伸閱讀:有關序列化的文章,豁然開朗
1、我對Java Serializable(序列化)的理解和總結
1)、序列化是干什么的?
簡單說就是為了保存在內存中的各種對象的狀態(也就是實例變量,不是方法),並且可以把保存的對象狀態再讀出來。雖然你可以用你自己的各種各樣的方法來保存object states,但是Java給你提供一種應該比你自己好的保存對象狀態的機制,那就是序列化。
2)、什么情況下需要序列化
a)當你想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;
b)當你想用套接字在網絡上傳送對象的時候;
c)當你想通過RMI傳輸對象的時候;
……
有關Java對象的序列化和反序列化也算是Java基礎的一部分,下面對Java序列化的機制和原理進行一些介紹。
Java序列化算法透析
Serialization(序列化)是一種將對象以一連串的字節描述的過程;反序列化deserialization是一種將這些字節重建成一個對象的過程。Java序列化API提供一種處理對象序列化的標准機制。在這里你能學到如何序列化一個對象,什么時候需要序列化以及Java序列化的算法,我們用一個實例來示范序列化以后的字節是如何描述一個對象的信息的。
序列化的必要性
Java中,一切都是對象,在分布式環境中經常需要將Object從這一端網絡或設備傳遞到另一端。這就需要有一種可以在兩端傳輸數據的協議。Java序列化機制就是為了解決這個問題而產生。
如何序列化一個對象
一個對象能夠序列化的前提是實現Serializable接口,Serializable接口沒有方法,更像是個標記。有了這個標記的Class就能被序列化機制處理。
……