程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 關於Java對象序列化您不知道的5件事(3)

關於Java對象序列化您不知道的5件事(3)

日期:2017/1/13 15:20:46      編輯:關於JAVA

3、序列化的數據可以被簽名和密封上一個技巧假設您想模糊化序列化數據,而不是對其加密或者確保它不被修改。當然,通過使用 writeObject 和 readObject 可以實現密碼加密和簽名管理,但其實還有更好的方式。

如果需要對整個對象進行加密和簽名,最簡單的是將它放在一個 javax.crypto.SealedObject 和/或 Java.security.SignedObject 包裝器中。兩者都是可序列化的,所以將對象包裝在 SealedObject 中可以圍繞原對象創建一種 “包裝盒”。必須有對稱密鑰才能解密,而且密鑰必須單獨管理。同樣,也可以將 SignedObject 用於數據驗證,並且對稱密鑰也必須單獨管理。

結合使用這兩種對象,便可以輕松地對序列化數據進行密封和簽名,而不必強調關於數字簽名驗證或加密的細節。很簡潔,是吧?

4. 序列化允許將代理放在流中

很多情況下,類中包含一個核心數據元素,通過它可以派生或找到類中的其他字段。在此情況下,沒有必要序列化整個對象。可以將字段標記為 transIEnt,但是每當有方法訪問一個字段時,類仍然必須顯式地產生代碼來檢查它是否被初始化。

如果首要問題是序列化,那麼最好指定一個 flyweight 或代理放在流中。為原始 Person 提供一個 writeReplace 方法,可以序列化不同類型的對象來代替它。類似地,如果反序列化期間發現一個 readResolve 方法,那麼將調用該方法,將替代對象提供給調用者。

打包和解包代理

writeReplace 和 readResolve 方法使 Person 類可以將它的所有數據(或其中的核心數據)打包到一個 PersonProxy 中,將它放入到一個流中,然後在反序列化時再進行解包。

清單 5. 你完整了我,我代替了你

  1. class PersonProxy
  2. implements Java.io.Serializable
  3. {
  4. public PersonProxy(Person orig)
  5. {
  6. data = orig.getFirstName() + "," + orig.getLastName()+ "," + orig.getAge();
  7. if (orig.getSpouse() != null)
  8. {
  9. Person spouse = orig.getSpouse();
  10. data = data + "," + spouse.getFirstName() + "," + spouse.getLastName() + ","+ spouse.getAge();
  11. }
  12. }
  13. public String data;
  14. private Object readResolve()
  15. throws Java.io.ObjectStreamException
  16. {
  17. String[] pIEces = data.split(",");
  18. Person result = new Person(pIEces[0], pIEces[1], Integer.parseInt(pIEces[2]));
  19. if (pIEces.length > 3)
  20. {
  21. result.setSpouse(new Person(pIEces[3], pIEces[4], Integer.parseInt
  22. (pIEces[5])));
  23. result.getSpouse().setSpouse(result);
  24. }
  25. return result;
  26. }
  27. }
  28. public class Person
  29. implements Java.io.Serializable
  30. {
  31. public Person(String fn, String ln, int a){
  32. this.firstName = fn; this.lastName = ln; this.age = a;
  33. }
  34. public String getFirstName() { return firstName; }
  35. public String getLastName() { return lastName; }
  36. public int getAge() { return age; }
  37. public Person getSpouse() { return spouse; }
  38. private Object writeReplace()
  39. throws Java.io.ObjectStreamException
  40. {
  41. return new PersonProxy(this);
  42. }
  43. public void setFirstName(String value) { firstName = value; }
  44. public void setLastName(String value) { lastName = value; }
  45. public void setAge(int value) { age = value; }
  46. public void setSpouse(Person value) { spouse = value; }
  47. public String toString()
  48. {
  49. return "[Person: firstName=" + firstName +
  50. " lastName=" + lastName +
  51. " age=" + age +
  52. " spouse=" + spouse.getFirstName() +
  53. "]";
  54. }
  55. private String firstName;
  56. private String lastName;
  57. private int age;
  58. private Person spouse;
  59. }

5. 信任,但要驗證

認為序列化流中的數據總是與最初寫到流中的數據一致,這沒有問題。但是,正如一位美國前總統所說的,“信任,但要驗證”。

對於序列化的對象,這意味著驗證字段,以確保在反序列化之後它們仍具有正確的值,“以防萬一”。為此,可以實現 ObjectInputValidation 接口,並覆蓋 validateObject() 方法。如果調用該方法時發現某處有錯誤,則拋出一個 InvalidObjectException。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved