• 使用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=张三  
  • 相关阅读:
    【题解】魔术棋子
    NHOI2019小结
    【题解】滑雪
    【题解】最大平台
    【题解】洪水
    【题解】N皇后问题
    【题解】四色定理
    使用Docker快速搭建Jenkins
    使用Docker快速搭建Gitlab
    测试用Docker Swarm环境搭建
  • 原文地址:https://www.cnblogs.com/eer123/p/7894918.html
Copyright © 2020-2023  润新知