1. 程式人生 > >使用XStream是實現XML與Java對象的轉換(6)--持久化

使用XStream是實現XML與Java對象的轉換(6)--持久化

light 自己的 map stc title 指定 reg 對象 框架

九、持久化

在第八節的示例中,當我們操作一組對象時,我們可以指定Writer、OutputStream來寫出序列化後的XML數據,我們還可以指定Reader、InputStream來讀取序列化後的XML數據。當我們需要寫出和讀取文件時都需要指定輸入輸出流,並且需要明確的調用輸入輸出方法來實現Java對象的序列化和反序列化,其實我們完全可以讓Java對象的序列化和反序列化操作隱性的、自動的完成,這就是我們要學的內容:PersistenceStrategy、XmlArrayList、XmlMap和XmlSet。

PersistenceStrategy是我們的持久化策略,定義了我們的存儲和讀取協議,是實際做存儲和讀取XML的工具。XStream框架提供的持久化策略只有FilePersistenceStrategy這一種,即將XML數據持久化到文件系統中,但是我們可以定義自己的持久化策略(比如持久化到數據庫中),只要繼承PersistenceStrategy接口就行了。

XmlArrayList、XmlMap和XmlSet是我們熟悉的3個集合工具類,它們可以讓我們以我們非常熟悉的方式操作Java對象,並且隱性的存儲和讀取為我們需要的XML。

下面我們以XmlArrayList為例來學習。

1,簡單的存儲

程序如下:

Java代碼
  1. package cn.tjpu.zhw.xml.xstream6;
  2. import java.io.File;
  3. import java.util.List;
  4. import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
  5. import com.thoughtworks.xstream.persistence.PersistenceStrategy;
  6. import com.thoughtworks.xstream.persistence.XmlArrayList;
  7. public class PersistenceMain {
  8. public static void main(String[] args) {
  9. //創建持久化策略(定義存儲工具和存儲位置)
  10. //註:d:/tmp是一個已存在的目錄,否則會報錯
  11. PersistenceStrategy strategy = new FilePersistenceStrategy(
  12. new File("d:/tmp"));
  13. //創建操作工具
  14. List list = new XmlArrayList(strategy);
  15. System.out.println("剛創建XmlArrayList對象時list.size()="+list.size());
  16. //添加數據
  17. list.add(new Person("張三"));
  18. list.add(new Person("李四"));
  19. list.add(new Person("毛毛"));
  20. list.add(new Person("大熊"));
  21. System.out.println("添加了4個元素之後list.size()="+list.size());
  22. //刪除“李四”
  23. list.remove(1);
  24. System.out.println("刪除了1個元素之後list.size()="+list.size());
  25. }
  26. }
  27. class Person {
  28. public Person(String name) {
  29. this.name = name;
  30. }
  31. private String name;
  32. public String getName() {
  33. return name;
  34. }
  35. public void setName(String name) {
  36. this.name = name;
  37. }
  38. public String toString() {
  39. return "Person對象的name=" + getName();
  40. }
  41. }

運行結果:

Java代碼
  1. 剛創建XmlArrayList對象時list.size()=0
  2. 添加了4個元素之後list.size()=4
  3. 刪除了1個元素之後list.size()=3

現在我們查看d:/tmp目錄,我們會發現有3個文件[email protected][email protected][email protected]。這3個文件就是我們存儲的3個Person對象,他們的內容分別是:

[email protected]文件:

Xml代碼
  1. <cn.tjpu.zhw.xml.xstream6.Person>
  2. <name>張三</name>
  3. </cn.tjpu.zhw.xml.xstream6.Person>

[email protected]文件

Xml代碼
  1. <cn.tjpu.zhw.xml.xstream6.Person>
  2. <name>毛毛</name>
  3. </cn.tjpu.zhw.xml.xstream6.Person>

[email protected]文件:

Xml代碼
  1. <cn.tjpu.zhw.xml.xstream6.Person>
  2. <name>大熊</name>
  3. </cn.tjpu.zhw.xml.xstream6.Person>

其實,在我們每一次調用add方法的時候,都有一次持久化過程,每次都會將文件寫入到d:/tmp目錄。

2,所有我們熟悉的操作方法

由於XmlArrayList、XmlMap和XmlSet繼承我們熟悉各個集合接口,所以我們可以向操作List、Map和Set一樣來操作我們的數據,所不同的是原來我們集合中的數據在內存中,現在卻在我們預定義的持久化策略中。

編寫程序如下:

Java代碼
  1. package cn.tjpu.zhw.xml.xstream6;
  2. import java.io.File;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
  6. import com.thoughtworks.xstream.persistence.PersistenceStrategy;
  7. import com.thoughtworks.xstream.persistence.XmlArrayList;
  8. public class UsageTestMain {
  9. // XmlArrayList的用法
  10. public static void main(String[] args) {
  11. // 創建持久化策略(定義存儲工具和存儲位置)
  12. // 註:d:/tmp是一個已存在的目錄,否則會報錯
  13. PersistenceStrategy strategy = new FilePersistenceStrategy(new File(
  14. "d:/tmp"));
  15. // 創建操作工具
  16. List list = new XmlArrayList(strategy);
  17. System.out.println("剛創建XmlArrayList對象時list.size()="+list.size());
  18. System.out.println();
  19. //獲取叠代器
  20. Iterator iter = list.iterator();
  21. System.out.println("******遍歷每一個元素******");
  22. //遍歷每一個元素
  23. while(iter.hasNext()){
  24. Person p = (Person)iter.next();
  25. System.out.println("當前元素p="+p);
  26. }
  27. }
  28. }

運行結果:

Java代碼
  1. 剛創建XmlArrayList對象時list.size()=3
  2. ******遍歷每一個元素******
  3. 當前元素p=Person對象的name=張三
  4. 當前元素p=Person對象的name=毛毛
  5. 當前元素p=Person對象的name=大熊

3,定制自己的轉換器(Local Converter)

由於內存中存儲了大量數據,我們可以使用文件系統暫存,內存中只記錄存放文件的目錄即可,這是我們可以自己定義一個轉換器:

Java代碼
  1. package cn.tjpu.zhw.xml.xstream6;
  2. import java.io.File;
  3. import java.util.ArrayList;
  4. import java.util.Collection;
  5. import com.thoughtworks.xstream.XStream;
  6. import com.thoughtworks.xstream.converters.Converter;
  7. import com.thoughtworks.xstream.converters.MarshallingContext;
  8. import com.thoughtworks.xstream.converters.UnmarshallingContext;
  9. import com.thoughtworks.xstream.io.HierarchicalStreamReader;
  10. import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
  11. import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
  12. import com.thoughtworks.xstream.persistence.XmlArrayList;
  13. //自己定義一個局部轉換器
  14. public final class LocalArrayListConverter implements Converter {
  15. private XStream xstream;
  16. public LocalArrayListConverter(XStream xstream) {
  17. this.xstream = xstream;
  18. }
  19. //將Collection對象序列化到文件中
  20. //註:序列化時內存中並沒有存放集合中的內容,只是暫存了這些文件存放的目錄
  21. public void marshal(Object source, HierarchicalStreamWriter writer,
  22. MarshallingContext context) {
  23. File dir = new File("d:/tmp");
  24. //創建持久化工具,並加載目錄中的所有文件
  25. XmlArrayList list = new XmlArrayList(
  26. new FilePersistenceStrategy(dir,xstream));
  27. context.convertAnother(dir);
  28. //生成文件
  29. list.addAll((Collection) source);
  30. }
  31. //從文件中讀取信息,反序列換為Collection對象
  32. //註:反序列化時會刪除暫存目錄下的所有文件
  33. public Object unmarshal(
  34. HierarchicalStreamReader reader,
  35. UnmarshallingContext context) {
  36. File directory = (File) context.convertAnother(null, File.class);
  37. //創建持久化工具,並加載目錄中的所有文件
  38. XmlArrayList persistentList = new XmlArrayList(
  39. new FilePersistenceStrategy(directory, xstream));
  40. //將已加載的信息復制一份到list中
  41. ArrayList list = new ArrayList(persistentList);
  42. //刪除所有文件
  43. persistentList.clear();
  44. //返回已加載的信息
  45. return list;
  46. }
  47. public boolean canConvert(Class type) {
  48. return type == ArrayList.class;
  49. }
  50. }

這個轉換器是轉換ArrayList對象的。

下面是我們的測試程序:

Java代碼
  1. package cn.tjpu.zhw.xml.xstream6;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.List;
  5. import com.thoughtworks.xstream.XStream;
  6. public class LocalConverterMain {
  7. public static void main(String[] args) {
  8. XStream xstream = new XStream();
  9. xstream.alias("volume", Volume.class);
  10. //使用自定義的轉換器LocalArrayListConverter來轉換Volume類的documents字段
  11. //這個轉換器是受限制的局部(local)轉換器,只能轉換Volume類的documents字段
  12. xstream.registerLocalConverter(Volume.class, "documents",
  13. new LocalArrayListConverter(xstream));
  14. //要轉換的對象
  15. Volume volume = new Volume();
  16. //創建集合
  17. Collection coll = new ArrayList();
  18. coll.add(1);
  19. coll.add(2.123d);
  20. coll.add(new Person("張三"));
  21. volume.documents.addAll(coll);
  22. System.out.println("******序列化******");
  23. //轉換XML
  24. String xml = xstream.toXML(volume);
  25. //輸出XML
  26. System.out.println(xml);
  27. System.out.println("******反序列化******");
  28. Volume v2 = (Volume)xstream.fromXML(xml);
  29. for(Object obj:v2.documents){
  30. System.out.println("obj="+obj);
  31. }
  32. }
  33. }
  34. abstract class AbstractDocument {
  35. String title;
  36. }
  37. class TextDocument extends AbstractDocument {
  38. List chapters = new ArrayList();
  39. }
  40. class ScannedDocument {
  41. List images = new ArrayList();
  42. }
  43. class Volume {
  44. List documents = new ArrayList();
  45. }

運行結果:

Java代碼
  1. ******序列化******
  2. <volume>
  3. <documents>d:\tmp</documents>
  4. </volume>
  5. ******反序列化******
  6. obj=Person對象的name=張三
  7. obj=Person對象的name=毛毛
  8. obj=Person對象的name=大熊
  9. obj=1
  10. obj=2.123
  11. obj=Person對象的name=張三

使用XStream是實現XML與Java對象的轉換(6)--持久化