Jaxb
这是一个Java自带的工具类模块,用于XML和对象之间的相互转换。
核心类
JAXBContext
类,是应用的入口,用于管理XML和JavaBean之间的绑定信息;Marshaller
接口,用于将Java对象序列化为XML;Unmarshaller
接口,用于将XML反序列化为Java对象。
核心注解
@XmlRootElement
,用于类级别的注解,对应于xml的根元素;@XmlElement
,用于类中属性的注解,对应于xml中的节点元素;@XmlElementWrapper
,用于数组或集合类属性的注解,对应于xml中数组类元素的包裹节点,一般与@XmlElement一起使用;@XmlAttribute
,用于Java对象中属性的注解,对应于xml中该对象节点的属性元素;@XmlAccessorType
,用于类级别的注解,表示Java对象的哪种类型的属性自动序列化;@XmlAccessorOrder
,用于类级别的注解,用于对xml的节点顺序进行控制;@XmlType
,用于类级别的注解,主要用于实现对象映射为xml时的节点顺序控制;@XmlTransient
,用于Java对象中属性的注解,表示注解的属性不参与序列化;
代码示例
1.基本示例–JavaBean to XML
示例JavaBean
@XmlRootElement(name="student")
public class Student {
@XmlElement(name="name")
private String name;
@XmlElement(name="address")
private String address;
// 省略get/set方法
...
}
JavaBean 映射为Xml的示例
public class Demo {
public static void main(String[] args) throws JAXBException {
Student student = new Student();
student.setName("小明");
student.setAddress("花果山");
// 实例化JAXBContext作为应用入口
JAXBContext jaxbContext = JAXBContext.newInstance(Student.class);
// 创建Marshaller对象,用于实现JavaBean映射为XML
Marshaller marshaller = jaxbContext.createMarshaller();
// 设置xml的编码格式,默认为utf-8
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
// 设置是否省略xm头声明信息
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
// 设置xml是否格式化输出
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 创建字符串Writer,用于生成XML字符串
StringWriter writer = new StringWriter();
marshaller.marshal(student, writer);
String str = writer.toString();
System.out.println(str);
}
}
2.基本示例–XML to JavaBean
使用上面示例的Student
类。
public class Demo {
public static void main(String[] args) throws JAXBException {
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?><student><name>小明</name><address>花果山</address></student>";
// 应用的入口,用于管理XML/Java绑定信息
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
// Unmarshaller接口,将XML数据反序列化为Java对象
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Student student = (Student ) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(root.toString());
}
}
3.特殊注解示例
3.1 @XmlElementWraper
这个注解用于对数组类或集合类属性进行注解。
@XmlRootElement
public class school {
@XmlElementWrapper(name="students")
@XmlElement(name="student")
private List<Student> students;
// 省略get/set方法
...
}
上面JavaBean映射出的XML格式如下:
<school>
<students>
<student>
<name>小明</name>
<address>花果山</address>
</student>
<student>
<name>小红</name>
<address>花果山</address>
</student>
</students>
</school>
如果没有使用@XmlElementWrapper
注解,数组节点会平铺在父节点下。上面的实体映射成的XML示例如下:
<school>
<student>
<address>花果山</address>
<name>小明</name>
</student>
<student>
<address>花果山</address>
<name>小红</name>
</student>
</school>
3.2 @XmlAttribute
这个是用于给节点元素添加属性。据我目前了解,使用起来不方便。示例入下:
@XmlRootElement
public void Teacher {
@XmlElement
private String name;
@XmlAttribute
private String version = "1.0";
// 省略get/set方法
...
}
Teacher
类映射的Xml示例如下:
<teacher version="1.0">
<name>李雷</name>
</teacher>
为什么说使用起来不方便呢?因为@XmlAttribute
只能用于给所属类对应的节点添加属性,而不能给所属类中参数也添加属性。在参数也具有属性时,就必须要将这个参数独立作为一个实体类,才能给这个参数添加属性。示例如下:
@XmlRootElement
public class Age {
@XmlValue
private Integer value;
@XmlAttribute
private String attr="integer";
// 省略get/set方法
...
}
@XmlRootElement
public class Person {
@XmlElement(name="age")
private Age age;
@XmlAttribute
private String attr = "男";
// 省略get/set方法
...
}
上面代码的Xml映射结果示例如下:
<person attr="男">
<age attr="integer">18</age>
</person>
在这里使用了@XmlValue
注解,这个注解是用于给一个节点元素添加值,详情下面再说。如果一个Xml中有很多叶子节点,都具有属性,那么就需要给这个叶子节点都创建一个实体类,使用起来就很不方便,零碎的小类会很多。
3.3 @XmlAccessorType
这个注解作用于类,控制了是否自动将JavaBean的参数或属性与Xml绑定。它的属性值有4个枚举值:
- XmlAccessType.PROPERTY:JavaBean中所有具有getter/setter对的成员变量自动与XML绑定;
- XmlAccessType.FIELD:JavaBean中的所有非静态的、非瞬时的参数域自动与XML绑定;
- XmlAccessType.PUBLIC_MEMBER:JavaBean中具有的public修饰的getter/setter对和每个public参数都会自动与XML绑定;
- XmlAccessType.NONE:JavaBean中的参数除非被特别添加注解,否则不会与XML绑定。
示例如下:
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlRootElement
public class Company {
private String name;
private String address;
private String owner;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public void setOwner(String owner) {
this.owner = owner;
}
}
在这个示例中,Company
有三个成员变量,其中name
具有完整的getter/setter方法对,address
没有getter/setter方法,owner
只有setter方法。这个类映射为Xml的结果如下:
<company>
<name>小明与小红科技有限公司</name>
</company>
其余三种注解的示例可以类推。
3.4 @XmlAccessorOrder
这个注解作用于类,用于控制JavaBean映射为Xml时的节点顺序。属性值有两个:
- XmlAccessOrder.UNDEFINED:顺序未定义,默认按照J字母顺序进行排列;
- XmlAccessOrder.ALPHABETICAL:按照字母顺序进行排列。
如果不使用该注解,节点顺序也是按照字母顺序排列。
示例如下
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Country {
private String name;
private String address;
// 省略getter/setter方法
}
映射的XML为:
<country>
<address>北纬34度,东经120度</address>
<name>神秘国</name>
</country>
3.5 @XmlType
该注解作用于类,主要用于自定义Xml节点顺序。示例如下:
@XmlType(propOrder={"size", "name", "address"})
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Classroom {
private String name;
private String address;
private Integer size;
// 省略getter/setter方法
}
生成的Xml示例如下:
<Classroom>
<size>120</size>
<name>小明的教室</name>
<address>A栋3楼</address>
</Classroom>
在使用@XmlType
自定义顺序时,@XmlAccessorOrder
作用被覆盖。
3.6 @XmlTransient
该注解用于类、成员变量、方法,用于标注该类/成员变量/方法不与Xml进行绑定。示例如下;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Restaurant {
private String name;
@XmlTransient
private String address;
// 省略getter/setter
}
生成的Xml示例如下:
<Restaurant>
<name>小明的餐馆</name>
</Restaurant>
4 监听器
Jaxb定义了一个监听器接口Marshaller.Listener
,可以在对象进行序列化之前和之后处理自定义的事件。
一个Marshaller
只能设置一个监听器。
public class CustomListener implements Marshaller.Listener {
@Override
public void beforeMarshal(Object source) {
super.beforeMarshal(source);
}
@Override
public void afterMarshal(Object source) {
super.afterMarshal(source);
}
}
在使用时,示例如下:
JAXBContext jaxbContext = JAXBContext.newInstance(Student.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setListener(new CustomListener());
...
5 schema
使用xjc
命令可以根据schema文件生成JavaBean;
在JavaBean与Xml相互转换时,也可以使用schema进行参数类型校验。