使用XStream是實現XML與Java對象的轉換(6)--持久化
九、持久化
在第八節的示例中,當我們操作一組對象時,我們可以指定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代碼- package cn.tjpu.zhw.xml.xstream6;
- import java.io.File;
- import java.util.List;
- import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
- import com.thoughtworks.xstream.persistence.PersistenceStrategy;
- import com.thoughtworks.xstream.persistence.XmlArrayList;
- public class PersistenceMain {
- public static void main(String[] args) {
- //創建持久化策略(定義存儲工具和存儲位置)
- //註:d:/tmp是一個已存在的目錄,否則會報錯
- PersistenceStrategy strategy = new FilePersistenceStrategy(
- new File("d:/tmp"));
- //創建操作工具
- List list = new XmlArrayList(strategy);
- System.out.println("剛創建XmlArrayList對象時list.size()="+list.size());
- //添加數據
- list.add(new Person("張三"));
- list.add(new Person("李四"));
- list.add(new Person("毛毛"));
- list.add(new Person("大熊"));
- System.out.println("添加了4個元素之後list.size()="+list.size());
- //刪除“李四”
- list.remove(1);
- System.out.println("刪除了1個元素之後list.size()="+list.size());
- }
- }
- class Person {
- public Person(String name) {
- this.name = name;
- }
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String toString() {
- return "Person對象的name=" + getName();
- }
- }
運行結果:
Java代碼- 剛創建XmlArrayList對象時list.size()=0
- 添加了4個元素之後list.size()=4
- 刪除了1個元素之後list.size()=3
現在我們查看d:/tmp目錄,我們會發現有3個文件[email protected]、[email protected]和[email protected]。這3個文件就是我們存儲的3個Person對象,他們的內容分別是:
Xml代碼- <cn.tjpu.zhw.xml.xstream6.Person>
- <name>張三</name>
- </cn.tjpu.zhw.xml.xstream6.Person>
Xml代碼
- <cn.tjpu.zhw.xml.xstream6.Person>
- <name>毛毛</name>
- </cn.tjpu.zhw.xml.xstream6.Person>
Xml代碼
- <cn.tjpu.zhw.xml.xstream6.Person>
- <name>大熊</name>
- </cn.tjpu.zhw.xml.xstream6.Person>
其實,在我們每一次調用add方法的時候,都有一次持久化過程,每次都會將文件寫入到d:/tmp目錄。
2,所有我們熟悉的操作方法
由於XmlArrayList、XmlMap和XmlSet繼承我們熟悉各個集合接口,所以我們可以向操作List、Map和Set一樣來操作我們的數據,所不同的是原來我們集合中的數據在內存中,現在卻在我們預定義的持久化策略中。
編寫程序如下:
Java代碼- package cn.tjpu.zhw.xml.xstream6;
- import java.io.File;
- import java.util.Iterator;
- import java.util.List;
- import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
- import com.thoughtworks.xstream.persistence.PersistenceStrategy;
- import com.thoughtworks.xstream.persistence.XmlArrayList;
- public class UsageTestMain {
- // XmlArrayList的用法
- public static void main(String[] args) {
- // 創建持久化策略(定義存儲工具和存儲位置)
- // 註:d:/tmp是一個已存在的目錄,否則會報錯
- PersistenceStrategy strategy = new FilePersistenceStrategy(new File(
- "d:/tmp"));
- // 創建操作工具
- List list = new XmlArrayList(strategy);
- System.out.println("剛創建XmlArrayList對象時list.size()="+list.size());
- System.out.println();
- //獲取叠代器
- Iterator iter = list.iterator();
- System.out.println("******遍歷每一個元素******");
- //遍歷每一個元素
- while(iter.hasNext()){
- Person p = (Person)iter.next();
- System.out.println("當前元素p="+p);
- }
- }
- }
運行結果:
Java代碼- 剛創建XmlArrayList對象時list.size()=3
- ******遍歷每一個元素******
- 當前元素p=Person對象的name=張三
- 當前元素p=Person對象的name=毛毛
- 當前元素p=Person對象的name=大熊
3,定制自己的轉換器(Local Converter)
由於內存中存儲了大量數據,我們可以使用文件系統暫存,內存中只記錄存放文件的目錄即可,這是我們可以自己定義一個轉換器:
Java代碼
- package cn.tjpu.zhw.xml.xstream6;
- import java.io.File;
- import java.util.ArrayList;
- import java.util.Collection;
- import com.thoughtworks.xstream.XStream;
- import com.thoughtworks.xstream.converters.Converter;
- import com.thoughtworks.xstream.converters.MarshallingContext;
- import com.thoughtworks.xstream.converters.UnmarshallingContext;
- import com.thoughtworks.xstream.io.HierarchicalStreamReader;
- import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
- import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
- import com.thoughtworks.xstream.persistence.XmlArrayList;
- //自己定義一個局部轉換器
- public final class LocalArrayListConverter implements Converter {
- private XStream xstream;
- public LocalArrayListConverter(XStream xstream) {
- this.xstream = xstream;
- }
- //將Collection對象序列化到文件中
- //註:序列化時內存中並沒有存放集合中的內容,只是暫存了這些文件存放的目錄
- public void marshal(Object source, HierarchicalStreamWriter writer,
- MarshallingContext context) {
- File dir = new File("d:/tmp");
- //創建持久化工具,並加載目錄中的所有文件
- XmlArrayList list = new XmlArrayList(
- new FilePersistenceStrategy(dir,xstream));
- context.convertAnother(dir);
- //生成文件
- list.addAll((Collection) source);
- }
- //從文件中讀取信息,反序列換為Collection對象
- //註:反序列化時會刪除暫存目錄下的所有文件
- public Object unmarshal(
- HierarchicalStreamReader reader,
- UnmarshallingContext context) {
- File directory = (File) context.convertAnother(null, File.class);
- //創建持久化工具,並加載目錄中的所有文件
- XmlArrayList persistentList = new XmlArrayList(
- new FilePersistenceStrategy(directory, xstream));
- //將已加載的信息復制一份到list中
- ArrayList list = new ArrayList(persistentList);
- //刪除所有文件
- persistentList.clear();
- //返回已加載的信息
- return list;
- }
- public boolean canConvert(Class type) {
- return type == ArrayList.class;
- }
- }
這個轉換器是轉換ArrayList對象的。
下面是我們的測試程序:
Java代碼- package cn.tjpu.zhw.xml.xstream6;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.List;
- import com.thoughtworks.xstream.XStream;
- public class LocalConverterMain {
- public static void main(String[] args) {
- XStream xstream = new XStream();
- xstream.alias("volume", Volume.class);
- //使用自定義的轉換器LocalArrayListConverter來轉換Volume類的documents字段
- //這個轉換器是受限制的局部(local)轉換器,只能轉換Volume類的documents字段
- xstream.registerLocalConverter(Volume.class, "documents",
- new LocalArrayListConverter(xstream));
- //要轉換的對象
- Volume volume = new Volume();
- //創建集合
- Collection coll = new ArrayList();
- coll.add(1);
- coll.add(2.123d);
- coll.add(new Person("張三"));
- volume.documents.addAll(coll);
- System.out.println("******序列化******");
- //轉換XML
- String xml = xstream.toXML(volume);
- //輸出XML
- System.out.println(xml);
- System.out.println("******反序列化******");
- Volume v2 = (Volume)xstream.fromXML(xml);
- for(Object obj:v2.documents){
- System.out.println("obj="+obj);
- }
- }
- }
- abstract class AbstractDocument {
- String title;
- }
- class TextDocument extends AbstractDocument {
- List chapters = new ArrayList();
- }
- class ScannedDocument {
- List images = new ArrayList();
- }
- class Volume {
- List documents = new ArrayList();
- }
運行結果:
Java代碼- ******序列化******
- <volume>
- <documents>d:\tmp</documents>
- </volume>
- ******反序列化******
- obj=Person對象的name=張三
- obj=Person對象的name=毛毛
- obj=Person對象的name=大熊
- obj=1
- obj=2.123
- obj=Person對象的name=張三
使用XStream是實現XML與Java對象的轉換(6)--持久化