使用XStream是实现XML与Java对象的变换(6)-持久化


使用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,简单的存储

  程序如下:

  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(); } }

  运行结果:

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

  现在我们查看d:/tmp目录,我们会发现有3个文件[email protected][email protected][email protected]。这3个文件就是我们存储的3个Person对象,他们的内容分别是:

  [email protected]文件:

  <cn.tjpu.zhw.xml.xstream6.Person> <name>张三</name> </cn.tjpu.zhw.xml.xstream6.Person>

  [email protected]文件

  <cn.tjpu.zhw.xml.xstream6.Person> <name>毛毛</name> </cn.tjpu.zhw.xml.xstream6.Person>

  [email protected]文件:

  <cn.tjpu.zhw.xml.xstream6.Person> <name>大熊</name> </cn.tjpu.zhw.xml.xstream6.Person>

  其实,在我们每一次调用add方法的时候,都有一次持久化过程,每次都会将文件写入到d:/tmp目录。

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

  由于XmlArrayList、XmlMap和XmlSet继承我们熟悉各个集合接口,所以我们可以向操作List、Map和Set一样来操作我们的数据,所不同的是原来我们集合中的数据在内存中,现在却在我们预定义的持久化策略中。

  编写程序如下:

  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); } } }

  运行结果:

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

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

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

  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.thoughtworknverters.Converter; import com.thoughtworknverters.MarshallingContext; import com.thoughtworknverters.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对象的。

  下面是我们的测试程序:

  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(); }

  运行结果:

  ******序列化****** <volume> <documents>d:\tmp</documents> </volume> ******反序列化****** obj=Person对象的name=张三 obj=Person对象的name=毛毛 obj=Person对象的name=大熊 obj=1 obj=2.123 obj=Person对象的name=张三

xml XML基础知识 程序开发

茎钢互撸娃 15 years, 11 months ago

Your Answer