一、XStream 定义
XStream
是一个简单的 JAVA
类库,其主要用于将对象序列化为 XML
,或者将 XML
反序列化为对象,可以轻易的见 JAVA
对象和 XML
结构来回转换。
二、XStream 特性
特性 | 特性结解释 |
---|---|
便于使用 | 提供了一套高层次的门面,可以简化常见的用例 |
无需映射 | 大多数对象可以序列化,无需指定映射 |
关于性能 | 速度和低内存占用是设计的关键部分,使其适用于大型对象图或具有高消息吞吐量的系统 |
洁净XML | 没有重复的信息通过反射获取,这样生产的 XML 比人类机器 JAVA 序列化便于阅读并且更加紧凑 |
不修改对象 | 序列化内部字段,包括私有字段和最终字段。支持非公共和内部类。类不需要具有默认构造函数 |
完整对象图支持 | 在对象模型中遇到的重复引用将得到维护。支持循环引用 |
与其他 XML API 集成 | 通过实现接口,XStream 可以直接与任何树结构(不仅仅是 XML )进行序列化 |
可定制的转换策略 | 可以注册策略,以允许定制如何将特定类型表示为XML |
安全框架 | 对非编组类型进行精细控制,以防止操纵输入引起安全性问题 |
错误消息 | 当由于 XML 格式错误而导致异常时,将提供详细的诊断信息以帮助隔离和解决问题 |
替代输出格式 | 模块化设计允许其他输出格式。XStream 当前附带 JSON 支持和变形 |
三、XStream 用途
常见用途
-
XStream
在运行时使用JAVA
反射机制对要进行序列化的对象树的结构进行探索,并不需要对对象作出修改。XStream
可以序列化内部字段,包括私private
和final
字段,并且支持非公开类以及内部类 -
在缺省情况下,
XStream
不需要配置映射关系,对象和字段将映射为同名XML
元素。但是当对象和字段名与XML
中的元素名不同时,XStream
支持指定别名。XStream
支持以方法调用的方式,或是JAVA
标注的方式指定别名 -
XStream
在进行数据类型转换时,使用系统缺省的类型转换器。同时,也支持用户自定义的类型转换器
用途归纳
- 传输
- 持久化
- 配置
- 单元测试
四、XStream 局限
-
如果使用增强模式,
XStream
可以重新实例化没有默认构造函数的类。但是如果使用不同的JVM (例如:JDK1.4)
或由于SecurityManager
而受到限制,则需要默认的构造函数。 -
增强模式对于恢复
< 1.5
的任何JDK
的最终字段也是必须的,这意味着内部类实例的反序列化。 -
自动检测注解可能会导致竞争资源的情况,预处理注释是安全的
五、XStream 使用
-
添加
XStream
的pom
依赖<!-- XML 解析工具 2020-11-16--> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.14</version> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <optional>true</optional> </dependency>
-
XStream
的基本使用@AllArgsConstructor @ToString public class Person implements Serializable { private int id; private String name; private int age; public static void main(String[] args) { Person person = new Person(1,"Rambo",100); XStream xStream = new XStream(); // XStream对象设置默认安全防护 XStream.setupDefaultSecurity(xStream); // 设置允许的类 xStream.allowTypes(new Class[]{Person.class}); String xml = xStream.toXML(person); System.out.println("将 Person 对象转换为 XML = \n" + xml); System.out.println("\n=================================\n"); Person personFromXML = (Person)xStream.fromXML(xml); System.out.println("将 XML 转为 Person 对象 = \n" + personFromXML.toString()); } }
将 Person 对象转换为 XML = <com.rambo.utils.Person> <id>1</id> <name>Rambo</name> <age>100</age> </com.rambo.utils.Person> ================================= 将 XML 转为 Person 对象 = Person(id=1, name=Rambo, age=100)
P.S
-
在使用
XStream
序列化时,对JAVABean
没有任何限制,JAVABean
的字段可以使私有的,也可以没有getter
和setter
方法,还可以没有默认构造函数 -
XStream
序列化XML
时可以允许用户使用不同的XML
解析器,用户可以使用一个标准的JAXP DOM
解析器或者JAVA 6
集成的STAX
解析器。这样用户就不需要依赖XPP3
的依赖库。
-
-
XStream
注解使用-
混叠是定制生成
XML
或者使用XStream
特定格式化XML
的一种技术手段。假设下面给出的XML
格式,用于序列化和反序列化Garden
对象 -
XML
格式<garden name="农夫果园"> <fruit> <fruitName>苹果</fruitName> <description>红富士</description> </fruit> <fruit> <fruitName>香蕉</fruitName> <description>国产香蕉</description> </fruit> </garden>
-
根据以上
XML
格式创建实体类@AllArgsConstructor @NoArgsConstructor @ToString @XStreamAlias("fruit") public class Fruit implements Serializable { private String fruitName; private String description; } @AllArgsConstructor @NoArgsConstructor @ToString @XStreamAlias("garden") public class Garden implements Serializable { @XStreamAsAttribute() @XStreamAlias("name") private String gardenName; @XStreamImplicit(itemFieldName = "fruit") private List<Fruit> fruits; public static void main(String[] args) { Fruit apple = new Fruit("苹果", "红富士"); Fruit banana = new Fruit("香蕉", "国产香蕉"); List<Fruit> fruits = new ArrayList<>(); fruits.add(apple); fruits.add(banana); Garden garden = new Garden("农夫果园", fruits); XStream xStream = new XStream(); // XStream对象设置默认安全防护 XStream.setupDefaultSecurity(xStream); // 设置允许的类 xStream.allowTypes(new Class[]{Garden.class}); // 应用 Bean 类的注解 xStream.processAnnotations(Garden.class); // 自动检测注解 xStream.autodetectAnnotations(true); String xml = xStream.toXML(garden); System.out.println(xml); System.out.println("\n=============================\n"); Garden gardenFromXML = (Garden)xStream.fromXML(xml); System.out.println(gardenFromXML.toString()); } }
-
运行结果
<garden name="农夫果园"> <fruit> <fruitName>苹果</fruitName> <description>红富士</description> </fruit> <fruit> <fruitName>香蕉</fruitName> <description>国产香蕉</description> </fruit> </garden> ============================= Garden(gardenName=农夫果园, fruits=[Fruit(fruitName=苹果, description=红富士), Fruit(fruitName=香蕉, description=国产香蕉)])
-