0.前言
1.安装
JAXB API被认为是Java EE API,因此不再包含在Java SE 9中的默认类路径中。在Java 11中,它们已从JDK中删除。
需要安装以下jar包,然后引入到项目即可。
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.2.0</version>
</dependency>
2.使用注意事项
- 被marshal的类,假如属性和对应的get方法都是
public
就会出现类的两个属性具有相同名称
告警 - 被marshal的类,需要引入
import javax.xml.bind.annotation.*;
- 被marshal的类,需要有默认的构造函数:
public Person() {}
- 操作JAXB的类,需要引入如下
import javax.xml.bind.JAXB;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
- 可以正常工作,但是有时候会出现如下警告
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.sun.xml.bind.v2.runtime.reflect.opt.Injector (file:/D:/Java/lib/jaxb-impl-2.3.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
WARNING: Please consider reporting this to the maintainers of com.sun.xml.bind.v2.runtime.reflect.opt.Injector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
3.使用:操作JAXB的类
3.1复杂方法
public void generateXML() {
Person person = new Person("abc", "男", "北京", "朝阳区");
File file = new File("E:\\person.xml");
JAXBContext jc = null;
try {
//根据Person类生成上下文对象
jc = JAXBContext.newInstance(Person.class);
//从上下文中获取Marshaller对象,用作将bean编组(转换)为xml
Marshaller ma = jc.createMarshaller();
//以下是为生成xml做的一些配置
//格式化输出,即按标签自动换行,否则就是一行输出
ma.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//设置编码(默认编码就是utf-8)
ma.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
//是否省略xml头信息,默认不省略(false)
ma.setProperty(Marshaller.JAXB_FRAGMENT, false);
//编组
ma.marshal(person, file);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public void generateBean() {
File file = new File("E:\\person.xml");
JAXBContext jc = null;
try {
jc = JAXBContext.newInstance(Person.class);
Unmarshaller uma = jc.createUnmarshaller();
Person person = (Person) uma.unmarshal(file);
System.out.println(person);
} catch (JAXBException e) {
e.printStackTrace();
}
}
3.2简单方法
public class JAXBTest {
public void generateXML() {
Person person = new Person("abc", "男", "北京", "朝阳区");
File file = new File("E:\\person.xml");
JAXB.marshal(person, file);
}
public void generateBean() {
File file = new File("E:\\person.xml");
Person person = JAXB.unmarshal(file, Person.class);
}
4.使用:被marshal的类的注释说明
4.1XmlRootElement
- 类级别的注解。将类映射为xml全局元素,也就是根元素。如果要使用 JAXB ,则该注解必不可少。
- 参数 name:用于指定生成元素的名字,若不指定,默认使用类名小写作为元素名。
- 参数 namespace:namespace属性用于指定生成的元素所属的命名空间。
@XmlRootElement(name="Student", namespace="http://www.w3cschool.org/jaxb2")
public class StudentC {
private String id;
}
生成的xml如下
<ns2:Student xmlns:ns2="http://www.w3cschool.org/jaxb2">
<age>22</age>
...
</ns2:Student>
4.2XmlAccessorType
- 类级别的注解。定义这个类中的何种类型需要映射到XML
- 参数value:
- XmlAccessType.FIELD:映射这个类中的所有字段到XML
- XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML
- XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)
- XmlAccessType.NONE:不映射
4.3@XmlElement
- 字段,方法,参数级别的注解。该注解可以将被注解的(非静态)字段,或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。不能同时添加到字段和方法。
- 参数 name:
- 参数 namespace:
- 参数 required
- 参数 nillable:是否处理空数据,默认为false
- 参数 type:定义该字段或属性的关联类型
4.4@XmlAttribute
- 字段和方法级别的注解。该注解会将字段或get/set方法对应的字段映射成本类对应元素的属性。
@XmlRootElement
public class Desk {
private String id;
private String owner;
@XmlAttribute
public void setId(String id) { }
}
生成的XML如下
desk id="004">
<owner>Tom</owner>
</desk>
4.5@XmlTransient
- 类,字段,方法级别的注解。定义某一字段或属性不需要被映射。该注解与所有其他JAXB注释相互排斥,也就是说与其他注释连用就会报错
- 不能和其他注解合用。没有参数
4.6XmlType
- 类级别的注解,常与@XMLRootElement,@XmlAccessorType一起使用。
- 参数 propOrder:指定映射XML时的节点顺序,使用该属性时,必须列出JavaBean对象中的所有字段,否则会报错。
@XmlType(name = "t1", propOrder = {"id" ,"age", "name"})
4.7@XmlElementWrapper
- 对一些list对象,此注解可以增加一层外包装
- @XmlElementWrapper(name = "args") 属性名字指定外包装的值
- 生成的xml如下:
- 如果没有指定这个属性,则没有外包装
<args>
<arg>
</arg>
<arg>
</arg>
</args>
5.常见报错及处理方法
5.1 java.lang.NullPointerException
- 报错代码
java.lang.NullPointerException
at com.sun.xml.bind.v2.ClassFactory.tryGetDeclaredConstructor(ClassFactory.java:137)
at com.sun.xml.bind.v2.ClassFactory.create0(ClassFactory.java:106)
at com.sun.xml.bind.v2.ClassFact
- 这个主要是因为JXAB在编码xml文件创建对象的时候,如果这个对象的某一个属性是一个对象,JXAB会用new符去新建这个对象。当这个对象不支持用new创建的时候就会报错。意思就是说JXAB无法创建这个对象。
- 如下代码就会报这个错误。
private ObservableList<DocType> docTypeData;
- 如下就不会
private ObservableList<DocType> docTypeData = FXCollections.observableArrayList();//指定初始化创建对象的方法
5.2 InvocationTargetException
- 这个主要是因为没有setter。。。创建相应的setter就行了。