摘要
本文主要通过对比使用 JAXB 和非 JAXB 进行 Java 对象转 XML 和 XML 转 Java 对象的方式来介绍 JAXB 的基本功能,让大家对 JAXB 有一个初步的体会。
考虑有如下这样两个 Class、Person 和 Address,其中 Person 持有一个 Address 的引用。
public class Person {
private Integer id;
private String name;
private Integer age;
private Address address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address {
private Integer id;
private String province;
private String city;
private String area;
private String other;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getOther() {
return other;
}
public void setOther(String other) {
this.other = other;
}
}
Java 对象转 XML
假设现在需要把一个 Person 类型的对象生成如下格式的 XML:
<person id="1" name="张三">
<address id="1">
<area>南山区</area>
<city>深圳市</city>
<other>其它</other>
<province>广东省</province>
</address>
<age>30</age>
</person>
基于 DOM 实现
在没有使用 JAXB 之前,比如使用 Dom 生成 XML 的方式,得如下编程:
@Test
public void geneByDom() throws Exception {
Person person = this.buildPerson();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document document = db.newDocument();
Element personEle = document.createElement("person");
personEle.setAttribute("id", person.getId().toString());
personEle.setAttribute("name", person.getName());
Element ageEle = document.createElement("age");
ageEle.setTextContent(person.getAge().toString());
personEle.appendChild(ageEle);
Address address = person.getAddress();
Element addressEle = document.createElement("address");
addressEle.setAttribute("id", address.getId().toString());
Element province = document.createElement("province");
province.setTextContent(address.getProvince());
addressEle.appendChild(province);
Element city = document.createElement("city");
city.setTextContent(address.getCity());
addressEle.appendChild(city);
Element area = document.createElement("area");
area.setTextContent(address.getArea());
addressEle.appendChild(area);
Element other = document.createElement("other");
other.setTextContent(address.getOther());
addressEle.appendChild(other);
personEle.appendChild(addressEle);
document.appendChild(personEle);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source xmlSource = new DOMSource(document);
//把生成的XML输出到控制台
Result outputTarget = new StreamResult(System.out);
transformer.transform(xmlSource, outputTarget);
}
基于 JAXB 实现
基于 JAXB 实现时需要通过 JAXB 提供的注解来控制它的一些行为,比如下面通过在 Person 类上 @XmlRootElement 指定它为一个根节点,对应的根节点名称将默认取类名称,然后首字母小写,在本示例中即取 “person”。通过 @XmlAttribute 指定 id 和 name 作为节点 person的XML 属性,可以通过 XmlAttribute 的 name 属性指定生成的 XML 属性的名称,如 getId() 方法上的 @XmlAttribute(name="id");没有指定 name 属性时对应的 XML 属性名称将使用 Java 属性名称,如 getName() 方法上的 @XmlAttribute。
@XmlRootElement
public class Person {
private Integer id;
private String name;
private Integer age;
private Address address;
@XmlAttribute(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address {
private Integer id;
private String province;
private String city;
private String area;
private String other;
@XmlAttribute(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getOther() {
return other;
}
public void setOther(String other) {
this.other = other;
}
}
想要生成目标格式的 XML,基于 Class 的配置就好了。接下来就是调用对应的 API 进行 XML 的转换了。通过如下几行代码就可以把一个 Person 对象生成需要的 XML 格式了。如果还有其他的类型的对象也需要生成 XML,我们只需要把下面代码中的对象和对应的类型更换一下即可,而同样的需求在基于 Dom 的转换中又得重新写一遍代码了,另外从代码层面可以明显的看出基于 JAXB 的方式比基于 DOM 的方式要节约很多代码,实现起来也要简单很多,它的 XML 绑定行为都是通过对应的注解来完成的,非常方便。
@Test
public void testMarshal() throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Person.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
//构造Person对象,不是本文的重点
Person person = this.buildPerson();
marshaller.marshal(person, writer);
System.out.println(writer.toString());
}
JAXB(Java Architecture for XML Binding)是一项可以通过 XML 产生 Java 对象,也可以通过 Java 对象产生 XML 的技术,是 JDK 自带的功能。JDK 中关于 JAXB 部分有几个比较重要的接口或类,如:
- JAXBContext:它是程序的入口类,提供了 XML/Java 绑定的操作,包括创建 Marshaller 和 Unmarshaller 等。
- Marshaller:它负责把 Java 对象序列化为对应的 XML。
- Unmarshaller:它负责把 XML 反序列化为对应的 Java 对象。
使用 JAXB 进行对象转 XML 的基本操作步骤如下:
//1、获取一个基于某个 class 的 JAXBContext,即 JAXB 上下文
JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
//2、利用 JAXBContext 对象创建对应的 Marshaller 实例
Marshaller marshaller = jaxbContext.createMarshaller();
//3、设置一些序列化时需要的指定的配置
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
StringWriter writer = new StringWriter();
//4、将对象进行序列化
marshaller.marshal(obj, writer);
- 创建一个 JAXB 上下文对象,可以传递序列化时需要用到的一些 Class,以便 JAXB 在序列化对应的对象时能够识别其中关联的 Class。
- 利用 JAXB 上下文对象创建对应的 Marshaller 对象。
- 指定序列化时的配置参数,具体可以设置的参数和对应的参数的含义可以参考 API 文档。
- 最后一步是将对应的对象序列化到一个 Writer、OutputStream、File 等输出对象中。
具体内容请参考:http://gitbook.cn/m/mazi/comp/column?columnId=5a210d8a39fa666a31fb0984