加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用 Simple 简化 XML 序列化

发布时间:2020-12-16 07:40:37 所属栏目:百科 来源:网络整理
导读:Simple 是什么? Simple 是一个 Java 框架,用于简化序列化和反序列化 XML 的过程。使用 Simple,开发人员可以简化(名字由此而来)将简单老 Java 对象(POJO)转换成 XML 文档的过程 — 即所谓的 序列化(serialization) 过程。Simple 也可促进相反的过程

Simple 是什么?

Simple 是一个 Java 框架,用于简化序列化和反序列化 XML 的过程。使用 Simple,开发人员可以简化(名字由此而来)将简单老 Java 对象(POJO)转换成 XML 文档的过程 — 即所谓的序列化(serialization)过程。Simple 也可促进相反的过程:开发人员可以将 XML 文档转换成 POJO — 即所谓的反序列化(deserialization)过程。

Simple 名副其实,它使用注解来支持序列化和反序列化过程。根据相应的 XML 文档应该如何出现,对 POJO 进行注解。一些字段被注解为属性,另一些字段被注解为元素。类通常被注解为根元素。在序列化过程中,该框架处理冗长的解释注解和产生相应 XML 文档的过程。无足为奇,在 XML 文档被转换成 POJO 的反序列化过程中,注解也会被解释。

使用 Simple 有几个优势。首先,它促进快速应用程序开发。Simple 是如此简单,它支持开发人员快速实现健壮的、使用 XML 序列化和反序列化的应用程序,无需完成长长的学习曲线以及付出繁重的开发劳动。

其次,Simple 不需要配置。前面已经提到,Simple 使用注解。这些注解取代了基于 XML 的配置文件(其他框架一般都有这样的配置文件)。

最后,Simple 只让使用它的应用程序增加少量的内存占用。Java 归档(Java Archive,JAR)文件只有 239 KB。Simple 也不依赖于一系列其他 JAR 文件,而其他框架则通常不是这样的。

获得 Simple

必须首先访问参考资源(下载地址:http://download.csdn.net/download/wplove1029/6607983)中列出的 Simple 网站下载归档文件,获得 Simple,然后才能使用它。但是关于这个过程,既有好消息,也有坏消息。好消息是,归档文件是免费的。坏消息是,归档文件是 .tar.gz 格式的。所以,您若是想用 Microsoft? Windows? 本机归档文件解压程序来打开这个归档文件的话,是会失望的。需要使用 WinZip 或其他类似的归档工具。

解压文件之后,注意在 jar 目录中有一个 JAR 文件(simple-xml-2.1.4.jar)。在编译时和运行时,类路径中需要有这个 JAR 文件。

序列化

将一个对象序列化成一个 XML 文档是一个相当简单的过程。涉及到两步:

  1. 创建具有适当注解的 POJO。
  2. 编写不多的几行代码,用于真正执行序列化过程。

为了本文目的,我们来回顾一下熟悉的鱼饵主题(当然只有读过我的文章的读者熟悉)。所以,清单 1是一个表示鱼饵信息的 POJO。


清单 1. Lure 类
@Root
public class Lure {

     @Attribute
     private String type;
	
     @Element
     private String company;
	
     @Element
     private int quantityInStock;
	
     @Element
     private String model;

     public String getType() {
		return type;
     }

     public void setType(String type) {
          this.type = type;
     }

     public String getCompany() {
          return company;
     }

     public void setCompany(String company) {
          this.company = company;
     }

     public int getQuantityInStock() {
          return quantityInStock;
     }

     public void setQuantityInStock(int quantityInStock) {
          this.quantityInStock = quantityInStock;
     }

     public String getModel() {
          return model;
     }

     public void setModel(String model) {
          this.model = model;
     }
}


这个 POJO 真的没有什么复杂的东西。其唯一可能初看起来不熟悉的部分是注解。同样,这是故意的。回想一下,Simple 框架的目的就是实现它名字的寓意。

@Root注解描述 XML 文档的根元素。因为每个 XML 文档都需要一个根元素,所以一定要记得包含这个元素。

type字段上面的@Attribute注解将该字段识别为属性。该属性被作为一个属性添加到根元素。

其余注解是@Element注解。这些注解位于以下 3 个字段的正上方:companyquantityInStockmodel。这些字段代表 XML 文档中的元素。

根据 JavaBean 标准,该 POJO 的其余部分由访问器(accessor)方法和 修改器(mutator)方法组成。

既然 POJO 已经创建完成了,下面就该编写序列化代码了。参见清单 2中的该代码。


清单 2. LureExample 类
				
public static void main(String[] args) {
     try {
          Serializer serializer = new Persister();
          Lure lure = new Lure();
          lure.setCompany("Donzai");
          lure.setModel("Marlin Buster");
          lure.setQuantityInStock(23);
          lure.setType("Trolling");
		
          File result = new File("lure.xml");
          serializer.write(lure,result);
     } catch (Exception e) {
          e.printStackTrace();
     }
}


第一件事就是实例化一个Persister对象。注意,该类是 Simple 框架的一部分,它实现Serializer接口。

接下来,实例化Lure对象并设置适当的字段。在本例中,制造鱼饵的公司名称是Donzai,模型的名字是Marlin Buster,库存数量是23。最后,鱼饵的类型是Trolling

再接下来,实例化一个File对象,它的名称是将成为 XML 文档的那个文件的名称。在本例中,该名称是 lure.xml。

最后,调用 serializer 来编写文件。write()方法中提供两个参数。第一个参数是 POJO,第二个参数是File对象。

现在可以执行该代码了。清单 2是一个 Java 应用程序,所以您可以使用自己喜欢的集成开发环境 (IDE) 来运行它。确保 simple-xml-2.1.4.jar 在类路径中。如果使用的是 Eclipse,只需在文件上右击,选择Run As,再从出现的菜单中选择Java Application即可。

如果一切正常(应该如此 — 这很简单,是不是?),那么产生的 XML 文档应该类似于清单 3


清单 3. LureExample 的输出
				
<lure type="Trolling">
   <company>Donzai</company>
   <quantityInStock>23</quantityInStock>
   <model>Marlin Buster</model>
</lure>


注意关于清单 3的几点。首先,注意 lure 类型是根元素的一个属性。这没有疑义,因为前面在 POJO 中是用@Attribute而不是@Element注解了type字段。

关于产生的 XML,另一个重点是元素名称遵循 JavaBean 标准。例如,根元素是lure,尽管类名称是Lure。3 个子元素名称完全匹配字段名称。同样,这也是有意为之,因为您不想要首字母大写的根元素,而子元素名称则遵循另外的模式。

反序列化

序列化一个对象是如此地容易,那么反序列化对象也很容易,对不对?对!

回想一下,反序列化是将 XML 文档转换成 POJO 的过程。很不错的是,可以使用刚才创建的 XML 文档来进行反序列化。

清单 4展示了反序列化代码。


清单 4. LureExample2 类
				
public static void main(String[] args) {
     try {
          Serializer serializer = new Persister();
          File source = new File("lure.xml");
          Lure lure = serializer.read(Lure.class,source);

          System.out.println(lure.getCompany());
          System.out.println(lure.getModel());
          System.out.println(lure.getQuantityInStock());
          System.out.println(lure.getType());
     } catch (Exception e) {
          e.printStackTrace();
     }
}

同样,首先是实例化一个实现Serializer接口的对象(Persister)。

另一个类似行是File对象的实例化。但是,这里有一个明显的不同。在清单 3中,是为一个不存在的文件实例化了File对象。此处假设(实际上必须这样)该文件已经存在。

接下来,通过从Serializer对象调用read方法,从而实例化 POJO。read方法有两个参数:POJO 的类和File对象,后者代表包含数据的 XML 文件。

最后,从 POJO 输出所有的信息,确保所有内容都读取正确。

执行该代码时,输出应该类似于清单 5


清单 5. LureExample2 的输出
				
Donzai
Marlin Buster
23
Trolling

全树序列化

至此,您所序列化和反序列化的 XML 文档都相当简单。

大多数 XML 文档要复杂多了。它们通常具有数层嵌套的元素,有时候还有一到多个重复的元素,每个元素又有几个子元素。

幸运的是,Simple 即使对于更复杂的文档也不违反它的名字的寓意。就像在一个 POJO 中嵌套又一个 POJO 那么简单。我们来看一下清单 6


清单 6. AdvancedLure 类
				
@Attribute
private String type;

@Element
private String company;
	
@Element
private int quantityInStock;
	
@Element
private String model;
	
@Element
private ConfigurationScheme configurationScheme;


清单 6中的AdvancedLure类非常类似于清单 1中描述的Lure类。一个例外之处是包含了另一个字段:configurationScheme。配置方案由另一个POJO 表示,描述在清单 7中。


清单 7. ConfigurationScheme 类
				
@Root
public class ConfigurationScheme {
	
@Element
private String color;
	
@Element
private int size;

为节省篇幅,我舍去了 accessor 方法和 mutator 方法。

清单 7中的注解应该看起来很熟悉。它们与清单 1中使用的是相同的注解。

这又将我们引向清单 8


清单 8. LureExample3 类
				
public static void main(String[] args) {
     try {
          Serializer serializer = new Persister();
          AdvancedLure lure = new AdvancedLure();
          lure.setCompany("Donzai");
          lure.setModel("Marlin Buster");
          lure.setQuantityInStock(23);
          lure.setType("Trolling");
			
          ConfigurationScheme configurationScheme = new ConfigurationScheme();
          configurationScheme.setColor("Blue");
          configurationScheme.setSize(3);
          lure.setConfigurationScheme(configurationScheme);
			
          File result = new File("advancedlure.xml");
          serializer.write(lure,result);
     } catch (Exception e) {
          e.printStackTrace();
     }
}

清单 8和清单 2之间最大的差别是,您在AdvancedLure对象中实例化了一个ConfigurationScheme对象并设置了适当的字段。

运行该代码,输出应该类似于清单 9


清单 9. LureExample3 的输出
				
<advancedLure type="Trolling">
   <company>Donzai</company>
   <quantityInStock>23</quantityInStock>
   <model>Marlin Buster</model>
   <configurationScheme>
      <color>Blue</color>
      <size>3</size>
   </configurationScheme>
</advancedLure>

可以看到,嵌套的元素与预期那样地被序列化。

枚举

XML 文档经常包含某些元素的枚举。也就是说,相同的元素名称可以重复,只不过带有不同的子元素或属性数据而已。幸运的是,Simple 也能够处理这种情况。

为了演示该特性,我们创建一个新的类,名叫Inventory,其中包含仓库(储存库存的地方)的名称和在该库存位置找到的鱼饵的列表,如清单 10中所示。


清单 10. Inventory 类
				
@Root
public class Inventory {
	
     @ElementList
     private List<AdvancedLure> lures;
	
     @Attribute
     private String warehouse;

注意,使用了一个新注解:@ElementList。该注解告诉 Simple 框架:相应的List对象代表 XML 元素的枚举。

用于演示该 POJO 的序列化的代码跟用于序列化更简单的 POJO(比如说清单 2中序列化的那个 POJO)的代码一样容易。唯一增加的复杂性来自于,为嵌套目的实例化了所有必需的对象。参见清单 11


清单 11. LureExample4 类
Serializer serializer = new Persister();

AdvancedLure lure = new AdvancedLure();
lure.setCompany("Donzai");
lure.setModel("Marlin Buster");
lure.setQuantityInStock(23);
lure.setType("Trolling");
			
ConfigurationScheme configurationScheme = new ConfigurationScheme();
configurationScheme.setColor("Blue");
configurationScheme.setSize(3);
lure.setConfigurationScheme(configurationScheme);
			
			
AdvancedLure lure2 = new AdvancedLure();
lure2.setCompany("Ziggi");
lure2.setModel("Tuna Finder");
lure2.setQuantityInStock(44);
lure2.setType("Trolling");
		
ConfigurationScheme configurationScheme2 = new ConfigurationScheme();
configurationScheme2.setColor("Red");
configurationScheme2.setSize(5);
lure2.setConfigurationScheme(configurationScheme2);
			
List<AdvancedLure> lures = new ArrayList<AdvancedLure>();
lures.add(lure);
lures.add(lure2);
			
Inventory inventory = new Inventory();
inventory.setLures(lures);
inventory.setWarehouse("Midwest");
			
File result = new File("inventory.xml");

serializer.write(inventory,result);


执行该代码时,会创建一个叫做 inventory.xml 的 XML 文件。该文件的内容应该类似于清单 12


清单 12. LureExample4 的输出
				
<inventory warehouse="Midwest">
   <lures>
      <advancedLure type="Trolling">
         <company>Donzai</company>
         <quantityInStock>23</quantityInStock>
         <model>Marlin Buster</model>
         <configurationScheme>
            <color>Blue</color>
            <size>3</size>
         </configurationScheme>
      </advancedLure>
      <advancedLure type="Trolling">
         <company>Ziggi</company>
         <quantityInStock>44</quantityInStock>
         <model>Tuna Finder</model>
         <configurationScheme>
            <color>Red</color>
            <size>5</size>
         </configurationScheme>
      </advancedLure>
   </lures>
</inventory>


可以看到,输出完全模仿清单 11中实例化及创建的 POJO。其中有两个advancedLure元素,它们各自包含用来填充相应 POJO 的数据。注意,嵌套也是允许的。

构造器

您的代码有可能使用永久不变的 POJO。在这种情况下,您可能会缺少用于修改字段属性的 setter 方法,相反,您依靠构造器来设置这些值。Simple 也能够处理这种情况。

在这种情况下,注解指定在构造器参数中,而不是放在字段名称上面。在适当 accessor 方法上面也需要注解。参见清单 13


清单 13. Inventory2 类
				
public Inventory2(@ElementList(name="lures") List<AdvancedLure> lures,@Attribute(name="warehouse") String warehouse) {
     this.lures = lures;
     this.warehouse = warehouse;
}

@ElementList(name="lures")
public List<AdvancedLure> getLures() {
     return lures;
}

@Attribute(name="warehouse")
public String getWarehouse() {
     return warehouse;
}

注意,在指定注解作为构造器参数的一部分时,也必须指定它对应的字段名称。对于第一个参数,字段名称是lures。对于第二个参数,字段名称是warehouse

然后提供 accessor 方法上面所匹配的注解和字段名称。在lures的 getter 方法的正上方,可以看到适当的注解,完全匹配构造器中使用的注解。类似地,warehouse的 getter 方法上面的注解也完全匹配该注解。

要执行该代码,只需对清单 11稍加修改,以包含清单 14中的代码。


清单 14. LureExample5 类
Inventory2 inventory = new Inventory2(lures,"MidWest");


使用清单 14中的代码,而不使用清单 11中使用的 setter 方法。其余都保持不变。

模板过滤器

Simple 的另一个伟大特性是,在反序列化 XML 文档时能够使用模板过滤器或默认值。

回到初始的 lure.xml,但是稍微修改一下,如清单 15所示。


清单 15. Lure2.xml 文档
				
<lure type="Trolling">
   <company>${lure.company}</company>
   <quantityInStock>23</quantityInStock>
   <model>Marlin Buster</model>
</lure>

注意 company 元素怎么不是包含实际的公司名称,而是包含一个类似于 Apache Ant 的变量声明?在本例中,变量的名称是lure.company

模板过滤器允许您用在运行时建立的实际的值代替变量声明。做到这一点最容易的一种方式是,利用一个Map对象将变量名与它的值相关联。然后使用该Map对象从 Simple 框架构造一个Filter对象。然后再使用该Filter对象构造Persister对象。我们来看一下清单 16


清单 16. LureExample6 类
				
Map<String,String> map = new HashMap<String,String>();
map.put("lure.company","Monmouth");
Filter filter = new MapFilter(map);
			
Serializer serializer = new Persister(filter);
File source = new File("lure2.xml");

Lure lure = serializer.read(Lure.class,source);

System.out.println(lure.getCompany());
System.out.println(lure.getModel());
System.out.println(lure.getQuantityInStock());
System.out.println(lure.getType());

清单 16与并没有大的差别。主要差别是,实例化了一个HashMap,用于将一个String值与一个String键相关联。本例中的String键果然是lure.company,即清单 15中使用的变量名。这里给它分配的值是Monmouth,而不是前面 XML 文档中的Donzai

清单 17。


清单 17. LureExample6 的输出
Monmouth Marlin Buster 23 Trolling

可以看到,模板过滤器用Map对象中与该键名关联的实际值取代了变量名lure.company。输出与预期完全一致。

结束语

如您所见,Simple 是一个健壮的 XML 序列化和反序列化框架。易于使用,无需配置,并且简化了开发工作。

Simple 有很多强大的特性,但是由于篇幅所限,这里只探讨了其中很少的几个特性。我强烈建议需要在软件开发项目中采用 XML 序列化和反序列化的开发人员考虑使用 Simple。


尊重原创,转载时请标注<人参米>原创.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读