参考文档链接:
https://blog.csdn.net/5iasp/article/details/38492825
https://blog.csdn.net/huanghanqian/article/details/51549066
1.概念
JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到 XML实例文档。 JAXB2.0是JDK 1.6的组成部分。我们不需要下载第三方jar包 即可做到轻松转换。
2.主要使用注解说明<特别重要注解已经加粗标注>
Marshaller接口,将Java对象序列化为XML数据。
Unmarshaller接口,将XML数据反序列化为Java对象。
@XmlType,将Java类或枚举类型映射到XML模式类型
@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标 注)字段到XML。其他值还有XmlAccessType.PROPERTY和XmlAccessType.NONE。
@XmlAccessorOrder,控制JAXB 绑定类中属性和字段的排序。
@XmlJavaTypeAdapter,使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。
@XmlElementWrapper ,对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。
@XmlRootElement,将Java类或枚举类型映射到XML元素。
@XmlElement,将Java类的一个属性映射到与属性同名的一个XML元素<XML标签的对应关系>。
@XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性<XML标签的属性对应关系>。
3.说明:本案例使用ClassEntity(班级)--->StudentEntity(学生) 对应关系1 : N 的模型进行讲解
对应实体类:ClassEntity
package com.mercy.bean;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
import java.util.List;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ClassEntity implements Serializable {
@XmlElement(name = "classId")
private Integer classId;
@XmlElement(name = "classNo")
private String classNo;
@XmlElement(name = "classCode")
private String classCode;
@XmlElement(name = "className")
private String className;
@XmlElementWrapper(name = "students", required = true)
@XmlElement(name = "student")
private List students;
public Integer getClassId() {
return classId;
}
public void setClassId(Integer classId) {
this.classId = classId;
}
public String getClassNo() {
return classNo;
}
public void setClassNo(String classNo) {
this.classNo = classNo;
}
public String getClassCode() {
return classCode;
}
public void setClassCode(String classCode) {
this.classCode = classCode;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List getStudents() {
return students;
}
public void setStudents(List students) {
this.students = students;
}
@Override
public String toString() {
return "ClassEntity{" +
"classId=" + classId +
", classNo='" + classNo + '\'' +
", classCode='" + classCode + '\'' +
", className='" + className + '\'' +
", students=" + students +
'}';
}
}
学生实体:StudentEntity
package com.mercy.bean;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import java.io.Serializable;
//@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class StudentEntity implements Serializable {
@XmlElement(name = "studentId")
private String studentId;
@XmlElement(name = "studentNo")
private String studentNo;
@XmlElement(name = "studentName")
private String studentName;
@XmlElement(name = "studentAge")
private String studentAge;
public String getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public void setStudentAge(String studentAge) {
this.studentAge = studentAge;
}
public String getStudentNo() {
return studentNo;
}
public void setStudentNo(String studentNo) {
this.studentNo = studentNo;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getStudentAge() {
return studentAge;
}
@Override
public String toString() {
return "StudentEntity{" +
"studentId=" + studentId +
", studentNo='" + studentNo + '\'' +
", studentName='" + studentName + '\'' +
", studentAge=" + studentAge +
'}';
}
}
XML 与 entity相互转换的工具类
package com.mercy.utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.*;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.namespace.QName;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
public class JAXBUtil {
private Logger logger = LoggerFactory.getLogger(getClass());
private JAXBContext jaxbContext;
public JAXBUtil(Class> clazz) {
try {
jaxbContext = JAXBContext.newInstance(clazz);
} catch (JAXBException e) {
logger.error("get jaxbContext instance fail:", e);
throw new RuntimeException(e);
}
}
/**
* Xml->Java Object.
*/
public Object toEntity(String xml) {
try {
StringReader reader = new StringReader(xml);
//Unmarshaller 此接口实现XML--->bean的转换
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
logger.error("unMarshalXml error:", e);
throw new RuntimeException(e);
}
}
/**
* Xml->Java Object, 支持大小写敏感或不敏感.
*/
public Object toEntityWithSensitive(String xml, boolean caseSensitive) {
try {
String fromXml = xml;
if (!caseSensitive)
fromXml = xml.toLowerCase();
StringReader reader = new StringReader(fromXml);
//Unmarshaller 此接口实现XML--->bean的转换
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
logger.error("unMarshalXml error:", e);
throw new RuntimeException(e);
}
}
/**
* Java Object->Xml.
*/
public String toXml(Object root, String encoding) {
try {
StringWriter writer = new StringWriter();
//创建marshaller 接口对象 实现BEAN--->xml转换
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
if (StringUtils.isNotBlank(encoding)) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
}
marshaller.marshal(root, writer);
return writer.toString();
} catch (JAXBException e) {
logger.error("marshaller Bean-->Xml error:", e);
throw new RuntimeException(e);
}
}
/**
* Java Object->Xml, 特别支持对Root Element是Collection的情形.
*/
@SuppressWarnings("unchecked")
public String toXmlWithWrapper(Collection root, String rootName, String encoding) {
try {
CollectionWrapper wrapper = new CollectionWrapper();
wrapper.collection = root;
JAXBElement wrapperElement =
new JAXBElement<>(new QName(rootName), CollectionWrapper.class, wrapper);
StringWriter writer = new StringWriter();
//创建marshaller 接口对象 实现BEAN--->xml转换
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
if (StringUtils.isNotBlank(encoding)) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
}
marshaller.marshal(wrapperElement, writer);
return writer.toString();
} catch (JAXBException e) {
logger.error("marshaller Bean-->Xml error:", e);
throw new RuntimeException(e);
}
}
/**
* 封装Root Element 是 Collection的情况.
*/
public static class CollectionWrapper {
@SuppressWarnings("unchecked")
@XmlAnyElement
Collection collection;
}
}
测试类
package com.mercy.test;
import com.mercy.bean.ClassEntity;
import com.mercy.utils.JAXBUtil;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class TestXmlToEntity {
//Marshaller接口,将Java对象序列化为XML数据。
//Unmarshaller接口,将XML数据反序列化为Java对象。
//@XmlType,将Java类或枚举类型映射到XML模式类型
//@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标 注)字段到XML。其他值还有XmlAccessType.PROPERTY和XmlAccessType.NONE。
//@XmlAccessorOrder,控制JAXB 绑定类中属性和字段的排序。
//@XmlJavaTypeAdapter,使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。
//@XmlElementWrapper ,对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。
//@XmlRootElement,将Java类或枚举类型映射到XML元素。
//@XmlElement,将Java类的一个属性映射到与属性同名的一个XML元素。
//@XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性。
/**
*
* 测试xml转为entity
*
*/
@Test
public void testXmlToEntity() throws Exception {
String fileSep = System.getProperty("file.separator");
File file = new File("D:\\github_rep\\jaxb_xml\\src\\main\\java\\com\\mercy\\xml\\class.xml");
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line); // 将读到的内容添加到 buffer 中
builder.append("\n"); // 添加换行符
}
String xml = builder.toString();
JAXBUtil jaxbUtil = new JAXBUtil(ClassEntity.class);
ClassEntity classEntity = (ClassEntity) jaxbUtil.toEntity(xml);
System.out.println(classEntity);
}
}
注意事项:
1.如果在属性上使用的注解@XmlAttribute 需要XML文档中标签存在对应的属性才能封装对应的值,不然获取封装的值为null
2.如果使用了注解@XmlElement 封装xml对应标签的值到bean的属性时。如果遇到报错信息:有两个名为XXX的属性,类的两个属性具有相同名称
产生的原因为:在定义对应实体类的时候定义了对应的属性然后再生成了对应属性的get/set方法造成属性名重复报错;
解决办法为:
a.删除对应的set/get方法或者属性定义申明;
b.在实体类上使用@XmlAccessorType(XmlAccessType.FIELD)控制xml与实体的属性绑定方式即可。