Java操作XML(8)--JAXB使用
JAXB(Java Architecture for XML Binding)是J2SE和J2EE平台的一部分,能够快速完成Java类和XML的互相映射。本文主要介绍JAXB的基本使用,文中所使用到的软件版本:Java 1.8.0_181。
1、JAXB简介
JAXB为XML节点和属性提供提供了各种面向对象的处理方式,可以基于注解或适配器将XML转换为Java对象。因为其优雅的处理方式,从JRE6开始,JAXB就已经成为了JRE的内置模块。
1.1、JAXB相关的重要类与接口
JAXBContext类 应用的入口,用于管理XML/Java绑定信息。
Marshaller接口 将Java对象序列化为XML数据。
Unmarshaller接口 将XML数据反序列化为Java对象。
1.2、JAXB注解
1.2.1、@XmlRootElement
类级别注解;将类映射为xml全局元素,也就是根元素。
参数 name 用于指定生成元素的名字,若不指定,默认使用类名小写作为元素名。
参数 namespace 用于指定生成的元素所属的命名空间。
@XmlRootElement(name = "class", namespace = "http://www.w3.org/TR/html4/school/") public class GradeJaxb { ... }
1.2.2、@XmlType
类级别注解;常与@XMLRootElement,@XmlAccessorType一起使用。
参数 name 定义XML Schema中type的名称
参数 namespace 指定Schema中的命名空间
参数 propOrder 指定映射XML时的节点顺序,使用该属性时,必须列出JavaBean对象中的所有字段,否则会报错。
参数 factoryClass 指定UnMarshal时生成映射类实例所需的工厂类,默认为这个类本身
参数 factoryMethod 指定工厂类的工厂方法
@XmlType(propOrder = {"marks", "firstname", "lastname", "nickname"}) public class StudentJaxb { private String firstname; private String lastname; private String nickname; private String marks; ... }
1.2.3、@XmlAccessorType
类级别注解;定义这个类中的何种类型需要映射到XML。
参数 value 可以接受4个指定值:
XmlAccessType.FIELD:映射这个类中的所有字段到XML
XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML
XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)
XmlAccessType.NONE:不映射
默认的容易导致"类的两个属性具有相同名称"的错误,一般可指定为XmlAccessType.FIELD
@XmlAccessorType(XmlAccessType.FIELD) public class StudentJaxb { ... }
1.2.4、@XmlElement
字段,方法,参数级别注解;该注解可以将被注解的(非静态)字段,或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。
参数 name 用于指定映射时的节点名称,指定生成元素的名字,若不指定,默认使用方法名小写作为元素名。
参数 namespace 指定映射时的节点命名空间
参数 required 字段是否必须,默认为false
参数 nillable 是否处理空数据,默认为false
参数 type 定义该字段或属性的关联类型
public class StudentJaxb { @XmlElement(namespace = "http://www.w3.org/TR/html4/school/") private String firstname; ... }
1.2.5、@XmlAttribute
字段和方法级别的注解。该注解会将字段或get/set方法对应的字段映射成本类对应元素的属性。
参数 name 用于指定映射时的节点属性名称,若不指定,默认使用方法名小写作为元素名。
参数 namespace 指定映射时的节点属性命名空间
参数 required 该属性是否必须,默认为false
public class StudentJaxb { @XmlAttribute private int rollno; @XmlAttribute(namespace = "http://www.w3.org/TR/html4/school/") private int age; ... }
1.2.6、@XmlTransient
类,字段,方法级别的注解。定义某一字段或属性不需要被映射。
2、JAXB使用
2.1、xml样例文件
<?xml version="1.0" encoding="utf-8" ?> <school:grade xmlns:school="http://www.w3.org/TR/html4/school/"> <school:student rollno="1" school:age="11"> <school:firstname>cxx1</school:firstname> <lastname>Bob1</lastname> <nickname>stars1</nickname> <marks>85</marks> </school:student> <school:student rollno="2" school:age="12"> <school:firstname>cxx2</school:firstname> <lastname>Bob2</lastname> <nickname>stars2</nickname> <marks>85</marks> </school:student> <school:student rollno="3" school:age="13"> <school:firstname>cxx3</school:firstname> <lastname>Bob3</lastname> <nickname>stars3</nickname> <marks>85</marks> </school:student> </school:grade>
2.2、xml对应的类
2.2.1、班级类
package com.abc.demo.general.xml; import javax.xml.bind.annotation.*; import java.util.List; /** * 班级 */ @XmlRootElement(name = "grade", namespace = "http://www.w3.org/TR/html4/school/") @XmlAccessorType(XmlAccessType.FIELD) public class GradeJaxb { @XmlElement(name = "student", namespace = "http://www.w3.org/TR/html4/school/") private List<StudentJaxb> students; public List<StudentJaxb> getStudents() { return students; } public void setStudents(List<StudentJaxb> students) { this.students = students; } @Override public String toString() { return "GradeJaxb{" + "students=" + students + '}'; } }
2.2.2、学生类
package com.abc.demo.general.xml; import javax.xml.bind.annotation.*; /** * 学生 */ @XmlType(propOrder = {"marks", "firstname", "lastname", "nickname"}) @XmlAccessorType(XmlAccessType.FIELD) public class StudentJaxb { @XmlAttribute private int rollno; @XmlAttribute(namespace = "http://www.w3.org/TR/html4/school/") private int age; @XmlElement(namespace = "http://www.w3.org/TR/html4/school/") private String firstname; private String lastname; private String nickname; private String marks; public StudentJaxb() {} public StudentJaxb(int rollno, int age, String firstname, String lastname, String nickname, String marks) { this.rollno = rollno; this.age = age; this.firstname = firstname; this.lastname = lastname; this.nickname = nickname; this.marks = marks; } public int getRollno() { return rollno; } public void setRollno(int rollno) { this.rollno = rollno; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getMarks() { return marks; } public void setMarks(String marks) { this.marks = marks; } @Override public String toString() { return "StudentJaxb{" + "rollno=" + rollno + ", age=" + age + ", firstname='" + firstname + '\'' + ", lastname='" + lastname + '\'' + ", nickname='" + nickname + '\'' + ", marks='" + marks + '\'' + '}'; } }
2.2.3、package-info.java
该文件定义命名空间对应的前缀.
/** * 设置命名空间对应的前缀 */ @XmlSchema(xmlns = {@XmlNs(prefix = "school", namespaceURI = "http://www.w3.org/TR/html4/school/")}) package com.abc.demo.general.xml; import javax.xml.bind.annotation.XmlNs; import javax.xml.bind.annotation.XmlSchema;
2.3、JAXB使用例子
该例子演示了使用JAXB来处理O/X转换:Java对象转成xml以及xml转成Java对象。
package com.abc.demo.general.xml; import org.junit.Test; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import java.io.InputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; /** * jaxb使用 */ public class JaxbCase { /** * java对象转成xml * @throws Exception */ @Test public void javaToXml() throws Exception { List<StudentJaxb> students = new ArrayList<>(); StudentJaxb student1 = new StudentJaxb(1, 11,"cxx1", "Bob1", "stars1", "85"); StudentJaxb student2 = new StudentJaxb(2, 12, "cxx2", "Bob2", "stars2", "85"); StudentJaxb student3 = new StudentJaxb(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); GradeJaxb grade = new GradeJaxb(); grade.setStudents(students); //获取JAXB的上下文环境 JAXBContext context = JAXBContext.newInstance(GradeJaxb.class); //创建Marshaller实例 Marshaller marshaller = context.createMarshaller(); //设置转换参数 -> 是否格式化输出 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); //是否隐藏xml声明 marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false); //构建输出环境 -> 这里输出到控制台Console PrintStream out = System.out; //将所需对象序列化 -> 该方法没有返回值 marshaller.marshal(grade, out); } /** * xml转成java对象 * @throws Exception */ @Test public void xmlToJava() throws Exception { //获取JAXB的上下文环境 JAXBContext context = JAXBContext.newInstance(GradeJaxb.class); //创建UnMarshaller实例 Unmarshaller unmarshaller = context.createUnmarshaller(); InputStream in = JaxbCase.class.getResourceAsStream("student2.xml"); //将XML数据序列化 GradeJaxb grade = (GradeJaxb) unmarshaller.unmarshal(in); System.out.println(grade); } }