使用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代码  
  1. package cn.tjpu.zhw.xml.xstream6;  
  2.    
  3. import java.io.File;  
  4. import java.util.List;  
  5.    
  6. import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;  
  7. import com.thoughtworks.xstream.persistence.PersistenceStrategy;  
  8. import com.thoughtworks.xstream.persistence.XmlArrayList;  
  9.    
  10. public class PersistenceMain {  
  11.    
  12.    public static void main(String[] args) {  
  13.       //创建持久化策略(定义存储工具和存储位置)  
  14.       //注:d:/tmp是一个已存在的目录,否则会报错  
  15.       PersistenceStrategy strategy = new FilePersistenceStrategy(  
  16.            new File("d:/tmp"));  
  17.        
  18.       //创建操作工具  
  19.       List list = new XmlArrayList(strategy);  
  20.       System.out.println("刚创建XmlArrayList对象时list.size()="+list.size());  
  21.        
  22.       //添加数据  
  23.       list.add(new Person("张三"));  
  24.       list.add(new Person("李四"));  
  25.       list.add(new Person("毛毛"));  
  26.       list.add(new Person("大熊"));  
  27.        
  28.       System.out.println("添加了4个元素之后list.size()="+list.size());  
  29.       //删除“李四”  
  30.       list.remove(1);  
  31.       System.out.println("删除了1个元素之后list.size()="+list.size());  
  32.    }  
  33.    
  34. }  
  35.    
  36. class Person {  
  37.    public Person(String name) {  
  38.       this.name = name;  
  39.    }  
  40.    
  41.    private String name;  
  42.    
  43.    public String getName() {  
  44.       return name;  
  45.    }  
  46.    
  47.    public void setName(String name) {  
  48.       this.name = name;  
  49.    }  
  50.    
  51.    public String toString() {  
  52.       return "Person对象的name=" + getName();  
  53.    }  
  54. }  

运行结果:

Java代码  
  1. 刚创建XmlArrayList对象时list.size()=0  
  2. 添加了4个元素之后list.size()=4  
  3. 删除了1个元素之后list.size()=3  

现在我们查看d:/tmp目录,我们会发现有3个文件int@0.xml、int@1.xml和int@2.xml。这3个文件就是我们存储的3个Person对象,他们的内容分别是:

int@0.xml文件:

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

int@1.xml文件

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

int@2.xml文件:

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.    
  3. import java.io.File;  
  4. import java.util.Iterator;  
  5. import java.util.List;  
  6.    
  7. import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;  
  8. import com.thoughtworks.xstream.persistence.PersistenceStrategy;  
  9. import com.thoughtworks.xstream.persistence.XmlArrayList;  
  10.    
  11. public class UsageTestMain {  
  12.    
  13.    // XmlArrayList的用法  
  14.    public static void main(String[] args) {  
  15.       // 创建持久化策略(定义存储工具和存储位置)  
  16.       // 注:d:/tmp是一个已存在的目录,否则会报错  
  17.       PersistenceStrategy strategy = new FilePersistenceStrategy(new File(  
  18.            "d:/tmp"));  
  19.    
  20.       // 创建操作工具  
  21.       List list = new XmlArrayList(strategy);  
  22.       System.out.println("刚创建XmlArrayList对象时list.size()="+list.size());  
  23.        
  24.       System.out.println();  
  25.        
  26.       //获取迭代器  
  27.       Iterator iter = list.iterator();  
  28.        
  29.       System.out.println("******遍历每一个元素******");  
  30.       //遍历每一个元素  
  31.       while(iter.hasNext()){  
  32.         Person p = (Person)iter.next();  
  33.         System.out.println("当前元素p="+p);  
  34.       }  
  35.    }  
  36.    
  37. }  

运行结果:

Java代码  
  1. 刚创建XmlArrayList对象时list.size()=3  
  2.    
  3. ******遍历每一个元素******  
  4. 当前元素p=Person对象的name=张三  
  5. 当前元素p=Person对象的name=毛毛  
  6. 当前元素p=Person对象的name=大熊  

3,定制自己的转换器(Local Converter)

由于内存中存储了大量数据,我们可以使用文件系统暂存,内存中只记录存放文件的目录即可,这是我们可以自己定义一个转换器:

Java代码  
  1. package cn.tjpu.zhw.xml.xstream6;  
  2.    
  3. import java.io.File;  
  4. import java.util.ArrayList;  
  5. import java.util.Collection;  
  6.    
  7. import com.thoughtworks.xstream.XStream;  
  8. import com.thoughtworks.xstream.converters.Converter;  
  9. import com.thoughtworks.xstream.converters.MarshallingContext;  
  10. import com.thoughtworks.xstream.converters.UnmarshallingContext;  
  11. import com.thoughtworks.xstream.io.HierarchicalStreamReader;  
  12. import com.thoughtworks.xstream.io.HierarchicalStreamWriter;  
  13. import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;  
  14. import com.thoughtworks.xstream.persistence.XmlArrayList;  
  15.    
  16. //自己定义一个局部转换器  
  17. public final class LocalArrayListConverter implements Converter {  
  18.    private XStream xstream;  
  19.    
  20.    public LocalArrayListConverter(XStream xstream) {  
  21.       this.xstream = xstream;  
  22.    }  
  23.    
  24.    //将Collection对象序列化到文件中  
  25.    //注:序列化时内存中并没有存放集合中的内容,只是暂存了这些文件存放的目录  
  26.    public void marshal(Object source, HierarchicalStreamWriter writer,  
  27.         MarshallingContext context) {  
  28.       File dir = new File("d:/tmp");  
  29.       //创建持久化工具,并加载目录中的所有文件  
  30.       XmlArrayList list = new XmlArrayList(  
  31.            new FilePersistenceStrategy(dir,xstream));  
  32.       context.convertAnother(dir);  
  33.       //生成文件  
  34.       list.addAll((Collection) source);  
  35.    }  
  36.    
  37.    //从文件中读取信息,反序列换为Collection对象  
  38.    //注:反序列化时会删除暂存目录下的所有文件  
  39.    public Object unmarshal(  
  40.         HierarchicalStreamReader reader,  
  41.         UnmarshallingContext context) {  
  42.       File directory = (File) context.convertAnother(null, File.class);  
  43.       //创建持久化工具,并加载目录中的所有文件  
  44.       XmlArrayList persistentList = new XmlArrayList(  
  45.            new FilePersistenceStrategy(directory, xstream));  
  46.       //将已加载的信息复制一份到list中  
  47.       ArrayList list = new ArrayList(persistentList);  
  48.       //删除所有文件  
  49.       persistentList.clear();  
  50.       //返回已加载的信息  
  51.       return list;  
  52.    }  
  53.    
  54.    public boolean canConvert(Class type) {  
  55.       return type == ArrayList.class;  
  56.    }  
  57. }  

这个转换器是转换ArrayList对象的。

下面是我们的测试程序:

Java代码  
  1. package cn.tjpu.zhw.xml.xstream6;  
  2.    
  3. import java.util.ArrayList;  
  4. import java.util.Collection;  
  5. import java.util.List;  
  6.    
  7. import com.thoughtworks.xstream.XStream;  
  8.    
  9. public class LocalConverterMain {  
  10.    
  11.    public static void main(String[] args) {  
  12.       XStream xstream = new XStream();  
  13.       xstream.alias("volume", Volume.class);  
  14.        
  15.       //使用自定义的转换器LocalArrayListConverter来转换Volume类的documents字段  
  16.       //这个转换器是受限制的局部(local)转换器,只能转换Volume类的documents字段  
  17.       xstream.registerLocalConverter(Volume.class, "documents",  
  18.            new LocalArrayListConverter(xstream));  
  19.    
  20.       //要转换的对象  
  21.       Volume volume = new Volume();  
  22.        
  23.       //创建集合  
  24.       Collection coll = new ArrayList();  
  25.       coll.add(1);  
  26.       coll.add(2.123d);  
  27.       coll.add(new Person("张三"));  
  28.       volume.documents.addAll(coll);  
  29.    
  30.       System.out.println("******序列化******");  
  31.       //转换XML  
  32.       String xml = xstream.toXML(volume);  
  33.        
  34.       //输出XML  
  35.       System.out.println(xml);  
  36.        
  37.       System.out.println("******反序列化******");  
  38.       Volume v2 = (Volume)xstream.fromXML(xml);  
  39.       for(Object obj:v2.documents){  
  40.         System.out.println("obj="+obj);  
  41.       }  
  42.    }  
  43.    
  44. }  
  45.    
  46. abstract class AbstractDocument {  
  47.    String title;  
  48. }  
  49.    
  50. class TextDocument extends AbstractDocument {  
  51.    List chapters = new ArrayList();  
  52. }  
  53.    
  54. class ScannedDocument {  
  55.    List images = new ArrayList();  
  56. }  
  57.    
  58. class Volume {  
  59.    List documents = new ArrayList();  
  60. }  

运行结果:

Java代码  
  1. ******序列化******  
  2. <volume>  
  3.   <documents>d: mp</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=张三  
原文地址:https://www.cnblogs.com/eer123/p/7894918.html