2021-03-07_JAXB

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:
  1. XmlAccessType.FIELD:映射这个类中的所有字段到XML
  2. XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML
  3. XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)
  4. 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就行了。

6.引用

1.JAXB常用注解讲解(超详细)
2.JABX 教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容