使用 Simple 简化 XML 序列化
真正简化从 Java 对象转换到 XML 的过程 Java? 开发人员在序列化和反序列化可扩展标记语言(Extensible Markup Language,XML)对象时有多种不同的选择。Simple 就是这样的一个例子,并且它有很多超越其他竞争方案的优势。本文概要介绍如何在 XML 通信系统中使用 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必须首先访问 参考资源 中列出的 Simple 网站下载归档文件,获得 Simple,然后才能使用它。但是关于这个过程,既有好消息,也有坏消息。好消息是,归档文件是免费的。坏消息是,归档文件是 .tar.gz 格式的。所以,您若是想用 Microsoft? Windows? 本机归档文件解压程序来打开这个归档文件的话,是会失望的。需要使用 WinZip 或其他类似的归档工具。 解压文件之后,注意在 jar 目录中有一个 JAR 文件(simple-xml-2.1.4.jar)。在编译时和运行时,类路径中需要有这个 JAR 文件。 序列化将一个对象序列化成一个 XML 文档是一个相当简单的过程。涉及到两步:
为了本文目的,我们来回顾一下熟悉的鱼饵主题(当然只有读过我的文章的读者熟悉)。所以,清单 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 框架的目的就是实现它名字的寓意。
其余注解是 根据 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(); } } 第一件事就是实例化一个 接下来,实例化 再接下来,实例化一个 最后,调用 serializer 来编写文件。 现在可以执行该代码了。清单 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 中是用 关于产生的 XML,另一个重点是元素名称遵循 JavaBean 标准。例如,根元素是 反序列化序列化一个对象是如此地容易,那么反序列化对象也很容易,对不对?对! 回想一下,反序列化是将 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(); } } 同样,首先是实例化一个实现 另一个类似行是 接下来,通过从 最后,从 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 中的 清单 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 之间最大的差别是,您在 运行该代码,输出应该类似于 清单 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 也能够处理这种情况。 为了演示该特性,我们创建一个新的类,名叫 清单 10. Inventory 类@Root public class Inventory { @ElementList private List<AdvancedLure> lures; @Attribute private String warehouse; 注意,使用了一个新注解: 用于演示该 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。其中有两个 构造器您的代码有可能使用永久不变的 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; } 注意,在指定注解作为构造器参数的一部分时,也必须指定它对应的字段名称。对于第一个参数,字段名称是 然后提供 accessor 方法上面所匹配的注解和字段名称。在 要执行该代码,只需对 清单 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 的变量声明?在本例中,变量的名称是 模板过滤器允许您用在运行时建立的实际的值代替变量声明。做到这一点最容易的一种方式是,利用一个 清单 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 与 清单 2 并没有大的差别。主要差别是,实例化了一个 执行该代码时,输出应该类似于 清单 17。 清单 17. LureExample6 的输出Monmouth Marlin Buster 23 Trolling 可以看到,模板过滤器用 结束语如您所见,Simple 是一个健壮的 XML 序列化和反序列化框架。易于使用,无需配置,并且简化了开发工作。 Simple 有很多强大的特性,但是由于篇幅所限,这里只探讨了其中很少的几个特性。我强烈建议需要在软件开发项目中采用 XML 序列化和反序列化的开发人员考虑使用 Simple。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |