JAXB常用注解讲解(超详细)

简介:

JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

一个简单的例子

Person.class类

package io.renren.modules.temptest;

import lombok.Data;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author xubo
 * @ClassNme Person
 * @Description TODO
 * @Date 2022-03-30 17:03:29
 * @version1.0
 */
@Data
@XmlRootElement //关于这个注解稍后会有解释
public class Person {

    private int id;
    private String name;
    private String gender;
    private String addr;
    private String area;

    public Person() {
    }

    public Person( String name, String gender, String addr, String area) {//这里没有id

        this.name = name;
        this.gender = gender;
        this.addr = addr;
        this.area = area;
    }



}

JAXBTest.class类:

package io.renren.modules.temptest;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;

/**
 * @author xubo
 * @ClassNme JAXBTest
 * @Description TODO
 * @Date 2022-03-30 17:08:26
 * @version1.0
 */

public class JAXBTest {

    //对象转xml
    public void generateXML() {
        Person person = new Person("abc", "男", "北京", "朝阳区");

        File file = new File("D:\\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();
        }
    }


    //xml转对象
    public void generateBean() {
        File file = new File("D:\\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();
        }
    }



}

Test.class类:

package io.renren.modules.temptest;

/**
 * @author xubo
 * @ClassNme Test
 * @Description TODO
 * @Date 2022-03-30 17:52:48
 * @version1.0
 */
public class Test {
    public static void main(String[] args){
        JAXBTest jaxbTest = new JAXBTest();
        //对象转xml
        jaxbTest.generateXML();

        //xml转对象
        jaxbTest.generateBean();

    }

}

测试结果:

运行方法:generateXML():

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <addr>北京</addr>
    <area>朝阳区</area>
    <gender></gender>
    <id>0</id>
    <name>abc</name>
</person>

此xml相当于该xsd文件:

<xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="addr" minOccurs="0"/>
        <xs:element type="xs:string" name="area" minOccurs="0"/>
        <xs:element type="xs:string" name="gender" minOccurs="0"/>
        <xs:element type="xs:int" name="id" minOccurs="0"/>
        <xs:element type="xs:string" name="name" minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

运行方法:generateBean():

是不是很方便?这只是一个最简单的小例子,下文会在这个例子的基础上介绍和讲解其他的一些常用JAXB注解。因为会使用到部分xsd的知识,不了解的读者可以看我另一篇博客:《xsd学习:超详细解析》,否则下文会有些理解困难。

注:从jdk1.7开始,JAXB就对解组和编组的方法进行了更简单的封装,所以实际项目中除非自己要进行个性化设置,否则大可不用自己再创建JAXBContext实例,直接通过JAXB静态调用相应的工具方法就行了,于是上面的测试方法可以写的更简练些:

下面为了测试方便,还是在JAXBTest类中写了两个静态方法,运行后结果还是一样的。代码看起来更加简洁,这只是简单的功能。

package io.renren.modules.temptest;

import javax.xml.bind.JAXB;
import java.io.File;

/**
 * @author xubo
 * @ClassNme Test
 * @Description TODO
 * @Date 2022-03-30 17:52:48
 * @version1.0
 */
public class Test {
    public static void main(String[] args){
//        JAXBTest jaxbTest = new JAXBTest();
//        //对象转xml
//        jaxbTest.generateXML();
//
//        //xml转对象
//        jaxbTest.generateBean();


        generateXML1();

        generateBean1();
    }



     //为了测试方便使用静态
        public static void generateXML1() {
            Person person = new Person("abc", "男", "北京", "朝阳区");
            File file = new File("D:\\person1.xml");
            JAXB.marshal(person, file);
        }

     
        public static void generateBean1() {
            File file = new File("D:\\person1.xml");
            Person person = JAXB.unmarshal(file, Person.class);

            System.out.println(person);
        }


}

结果显示:上面修改了生成文件名名字person1.xml

运行generateXML1()方法

运行generateBean1()方法

 

 直接使用默认的配置,已经足够应付大多数情况,读者可以试一下。

常用注解:

@XmlRootElement:

作用和用法:

类级别的注解,将类映射为xml全局元素,也就是根元素。就像spring配置文件中的beans。上面的例子中我将该注解用在了person类上,生成了<person>根元素。常与@XmlType,@XmlAccessorType,@XmlAccessorOrder连用。

属性:

该注解含有name和namespace两个属性。namespace属性用于指定生成的元素所属的命名空间。name属性用于指定生成元素的名字,若不指定则默认使用类名小写作为元素名。修改上面的例子,在该注解上使用name,namespace属性:

package io.renren.modules.temptest;

import lombok.Data;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author xubo
 * @ClassNme Person
 * @Description TODO
 * @Date 2022-03-30 17:03:29
 * @version1.0
 */
@Data
@XmlRootElement(name = "xubo" , namespace = "www.baidu.com")
public class Person {

    private int id;
    private String name;
    private String gender;
    private String addr;
    private String area;

    public Person() {
    }

    public Person( String name, String gender, String addr, String area) {//这里没有id

        this.name = name;
        this.gender = gender;
        this.addr = addr;
        this.area = area;
    }
}

重新运行方法generateXML1(),可以看到根元素变名字了,注意根元素跟之前不一样了,多了ns2

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:xubo xmlns:ns2="www.baidu.com">
    <addr>北京市</addr>
    <area>朝阳区潘家园</area>
    <gender></gender>
    <id>0</id>
    <name>abccc</name>
</ns2:xubo>

插播一段,我是参考大佬文章然后手动运算了一遍,注意我的最上面的Person.class类里面跟原文章是有区别的,区别指出在没有写get set 方法,使用了@Data注解,自然也没有添加在set方法上面添加@XmlElement注解,我是在学习注解的时候才发现我自己的Person类是没有添加该注解的,但是运行后的xml文件显示也是正常的,这点我暂时还不懂原因是什么。

原主的文章中的person是这样子

@XmlRootElement
public class Person {
    private int id;
    private String name;
    private String gender;
    private String addr;
    private String area;
 
    public Person() {
    }
 
    public Person(String name, String gender, String addr, String area) {
        this.name = name;
        this.gender = gender;
        this.addr = addr;
        this.area = area;
    }
 
    public int getId() {
        return id;
    }
 
    @XmlElement
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    @XmlElement
    public void setName(String name) {
        this.name = name;
    }
 
    public String getGender() {
        return gender;
    }
 
    @XmlElement
    public void setGender(String gender) {
        this.gender = gender;
    }
 
    public String getAddr() {
        return addr;
    }
 
    @XmlElement
    public void setAddr(String addr) {
        this.addr = addr;
    }
 
    public String getArea() {
        return area;
    }
 
    @XmlElement
    public void setArea(String area) {
        this.area = area;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", addr='" + addr + '\'' +
                ", area='" + area + '\'' +
                '}';
    }
}

为了学习的方便我们这里修改一下代码,

@XmlElement

作用和用法:

字段,方法,参数级别的注解。该注解可以将被注解的字段(非静态),或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。默认使用字段名或get/set方法去掉前缀剩下部分小写作为元素名(在字段名和get/set方法符合命名规范的情况下)。上面例子中,id、addr、name、gender、area都被映射成了<person>元素的子元素。下文会配合@XmlAccessorType注解详细讲解该注解的用法。常与@XmlValue,@XmlJavaTypeAdapter,@XmlElementWrapper连用。

属性:

该注解的属性常用的属性有有:name、nillable、required、namespace、defaultValue

* name属性可以指定生成元素的名字,同@XmlRootElement注解的name属性一样,不再举例。

* nillable属性可以指定元素的文本值是否可以为空,默认为false。修改上面例子:

@XmlElement(nillable = true)
    public void setName(String name) {
    this.name = name;
}

则生成的xsd(为了节省篇幅,只截取必要的片段)为:

<xs:element name="name" type="xs:string" nillable="true" minOccurs="0"/>

* required属性可以指定该元素是否必须出现,默认为false,所以在xsd中会有对应的属性minOccurs="0"。修改该属性为true

@XmlElement(nillable = true, required = true)
    public void setName(String name) {
    this.name = name;
}

生成的xsd文件为:

<xs:element name="name" type="xs:string" nillable="true" minOccurs="1"/>

* namespace属性可以指定该元素所属的命名空间

* defaultValue属性可以指定该元素默认的文本值

@XmlAttribute,注意不能和@XmlAttribute用在同一个地方,否则不生效。下面会有验证。

作用和用法:

字段和方法级别的注解。该注解会将字段或get/set方法对应的字段映射成本类对应元素的属性,属性名默认使用字段名或get/set方法去掉前缀剩下部分首字母小写(在字段名和get/set方法符合命名规范的情况下)。修改上面例子:

@XmlAttribute
public void setGender(String gender) {
    this.gender = gender;
}

我实际操作,正确的应该和上面代码一样。不然好像@XmlAttribute不会生效

生成的xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <addr></addr>
    <area>林州市</area>
    <gender></gender>
    <id>0</id>
    <name>abc</name>
</person>

我修改后,把@XmlElement注解删除掉,

 生成的xml文件:gender本类对应元素的属性,位置变了。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person gender="男">
    <addr></addr>
    <area>林州市</area>
    <id>0</id>
    <name>abc</name>
</person>

对应的xsd:

<xs:element name="human">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="addr"/>
        <xs:element type="xs:string" name="area"/>
        <xs:element type="xs:byte" name="id"/>
        <xs:element type="xs:string" name="name"/>
      </xs:sequence>
      <xs:attribute type="xs:string" name="gender"/>
    </xs:complexType>
  </xs:element>

属性:

该注解有name,required,namespace三个属性。用法和@XmlElement注解相同,不再举例,可以自己尝试下。

@XmlTransient

作用和用法:

类,字段,方法级别的注解。可使JAXB在映射xml元素时忽略被注解的类,字段,get/set对应字段。需要注意的是该注解与所有其他JAXB注释相互排斥,也就是说与其他注释连用就会报错。修改上面例子:

@XmlTransient
public void setId(int id) {
    this.id = id;
}

生成的xml:id元素消失了。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person gender="男">
    <addr></addr>
    <area>林州市</area>
    <name>abc</name>
</person>

属性:

该注解没有属性。

@XmlAccessorType

作用和用法:

包和类级别的注解。javaEE的API对该注解的解释是:控制字段是否被默认序列化。通俗来讲,就是决定哪些字段或哪些get/set方法对应的字段会被映射为xml元素,需要注意的是字段或get/set方法的访问权限(public/private)会影响字段是否被映射为xml元素,下面会详细讲解。

属性:

该注解只有一个value属性,可取的值是一个名为XmlAccessType的枚举类型里的值,下面详细看一下这几个值分别有什么用:

XmlAccessType.PROPERTY:

官方解释:

Every getter/setter pair in a JAXB-bound class will be automatically bound to XML, unless annotated by {@link XmlTransient}.
jaxb绑定类中的每个getter/setter对都将自动绑定到XML,除非用@XmlTransient注释。
Fields are bound to XML only when they are explicitly annotated by some of the JAXB annotations.
只有在某些JAXB注释显式地注释字段时,字段才被绑定到XML。

补充:

1.当使用了该值,只要字段有对应的get/set方法对(注意是成对出现,只有其中一个不会发生映射),不需要使用@XmlElement注解,不论该方法的访问权限是什么(即使是private),jaxb就会将该字段映射成xml元素。不过最好加上@XmlElement注解,get/set方法任选一个即可,都加上会报错。

2.若在一个字段有set/get方法对但又在字段上添加@XmlElement注解会报属性重复的错误。

3.若没有set/get方法对,则需要在字段上使用@XmlElement注解才可以映射为xml元素,否则不会发生映射。

4.若get/set方法上使用了@XmlTransient注解,但想要对应字段发生映射,需要在对应字段上添加@XmlElement注解,此时不会报错,并将该字段映射为xml元素。

XmlAccessType.FIELD:

官方解释:

Every non static, non transient field in a JAXB-bound class will be automatically bound to XML, unless annotated by {@link XmlTransient}.
jaxb绑定类中的每个非静态、非瞬态字段都将自动绑定到XML,除非使用@XmlTransient进行注释。
Getter/setter pairs are bound to XML only when they are explicitly annotated by some of the JAXB annotations.
只有当某些JAXB注释显式地对getter/setter对进行注释时,它们才会绑定到XML。

补充:

1.每个非静态的字段(无论访问权限如何)都会被jaxb映射为xml元素,即使没有get/set方法对,即使没有使用@XmlElement元素,但最好加上该注解以表明该字段要被映射为xml元素。

2.虽然没有get/set方法对,也会发生映射,但加上get/set方法对也不会报错,因为我们经常会使用这两个方法。但注意,不能再在这两个方法上使用@XmlElement方法,否则会报属性重复的错误。

3.若在字段上使用了@XmlTransient注解,但还想让该字段发生映射,需要在该字段对应的get/set方法上添加@XmlElement

XmlAccessType.PUBLIC_MEMBER (该值为默认值):

官方解释:

Every public getter/setter pair and every public field will be automatically bound to XML, unless annotated by {@link XmlTransient}.
每个公共getter/setter对和每个公共字段都将自动绑定到XML,除非使用@XmlTransient注释。
Fields or getter/setter pairs that are private, protected, or defaulted to package-only access are bound to XML only when they areexplicitly annotated by the appropriate JAXB annotations.
只有在适当的JAXB注释显式地注释了字段或getter/setter对之后,才会将它们绑定到XML。

补充:

1.每个访问权限为public的字段,或者每个访问权限为public的get/set方法对,都会将字段映射为xml元素,即使不使用@XmlElement,但最好加上。不可同时存在public字段和对应的get/set方法对,不然会报属性重复的错误。

2.若使用@XmlElement注解,需要注意只能在字段或get/set方法添加,两者任选其一,否则会报属性重复的错误。

3.若字段不为public,get/set方法为public并使用了@XmlTransient,需要在字段上添加@XmlElement才会发生映射。

若字段为public并使用了@XmlTransient,get/set方法对不为public,需要在get/set方法上使用@XmlElement才会映射。

XmlAccessType.NONE:

官方解释:

None of the fields or properties is bound to XML unless they are specifically  annotated with some of the JAXB annotations.
任何字段或属性都不会绑定到XML,除非使用某些JAXB注释对它们进行特别注释。

补充:

任何字段,get/set方法对都不会发生映射,除非使用某些注解,如@XmlElement,@XmlElementWrapper等。

@XmlAccessorOrder

作用和用法:

包和类级别的注解。控制生成元素的顺序。

属性:

只有一个value属性,可取的值是一个名为XmlAccessOrder的枚举类型的两个值,XmlAccessOrder.ALPHABETICAL 和 XmlAccessOrder.UNDEFINED。默认为XmlAccessOrder.UNDEFINED,代表按照类中字段的顺序生成元素的顺序。

另一个值则代表按照字母表的顺序对生成的元素排序。但奇怪的是,只有jaxb按照field生成元素时,默认值才会生效,否则总是按照字母表的顺序排序。

 @XmlElementWrapper

 作用和用法:

字段和方法级别的注解。围绕被映射的xml元素生成包装元素。主要用在集合对象映射后生成包装映射结果的xml元素。 

修改上面的例子,添加一个Key类,在Person类中添加一个Key类的Set集合,修改如下:

Key类:

@XmlRootElement
public class Key {
    private String roomNum;
 
    public Key() {
    }
 
    public Key(String roomNum) {
        this.roomNum = roomNum;
    }
 
    public String getRoomNum() {
        return roomNum;
    }
 
    @XmlElement
    public void setRoomNum(String roomNum) {
        this.roomNum = roomNum;
    }
 
    @Override
    public String toString() {
        return "Key{" +
                "roomNum='" + roomNum + '\'' +
                '}';
    }
}

Person类:

@XmlRootElement(name = "human")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public class Person {
    ...
    private Set<Key> key = new HashSet<>();
 
    public Person() {
    }
 
    public Person(String name, String gender, String addr, String area) {
        this.name = name;
        this.gender = gender;
        this.addr = addr;
        this.area = area;
        key.add(new Key("001"));    //向集合中添加两个Key对象
        key.add(new Key("002"));
    }
    ...
 
    public Set<Key> getKey() {
        return key;
    }
 
    @XmlElement
    public void setKey(Set<Key> key) {
        this.key = key;
    }
}

生成的xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<human gender="男">
    <addr></addr>
    <area>林州市</area>
    <key>
        <roomNum>002</roomNum>
    </key>
    <key>
        <roomNum>001</roomNum>
    </key>
    <name>abc</name>
</human>

但同一元素应该需要被“包装”一下才显得有层次感,所以可以使用@XmlElementWrapper来实现

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<human gender="男">
    <addr></addr>
    <area>林州市</area>
    <keys>
        <key>
            <roomNum>002</roomNum>
        </key>
        <key>
            <roomNum>001</roomNum>
        </key>
    </keys>
    <name>abc</name>
</human>

这样是不是好多了?

属性:

该注解有name、nillable、namespace、required四个属性,用法同上,不再赘述。

@XmlJavaTypeAdapter

作用和用法:

包、类、字段,方法、参数级别的注解。解决java日期(Date),数字(Number)格式化问题。直接看例子,修改Person类,添加一个Date类型字段:

Person类:

package io.renren.modules.temptest;

import javax.xml.bind.annotation.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@XmlRootElement(name = "human")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public class Person {
private int id;
    private String name;
    private String gender;
    private String addr;
    private String area;

    public Person() {
    }

    private Set<Key> key = new HashSet<>();


    public Person(String name, String gender, String addr, String area) {
        this.name = name;
        this.gender = gender;
        this.addr = addr;
        this.area = area;
        key.add(new Key("001"));    //向集合中添加两个Key对象
        key.add(new Key("002"));
    }

    public Set<Key> getKey() {
        return key;
    }

    @XmlElementWrapper(name = "keys")
    @XmlElement
    public void setKey(Set<Key> key) {
        this.key = key;
    }

    public int getId() {
        return id;
    }

    @XmlTransient
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }


    private Date date = new Date();//添加的日期类是在这里,应该写上面的,主要是为了集中看起来方便一点


    public Date getDate() {
        return date;
    }

    @XmlElement
    public void setDate(Date date) {
        this.date = date;
    }

    @XmlElement
    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }


    @XmlAttribute
    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getAddr() {
        return addr;
    }

    @XmlElement
    public void setAddr(String addr) {
        this.addr = addr;
    }

    public String getArea() {
        return area;
    }

    @XmlElement
    public void setArea(String area) {
        this.area = area;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", addr='" + addr + '\'' +
                ", area='" + area + '\'' +
                '}';
    }
}

生成的xml文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<human gender="男">
    <addr></addr>
    <area>林州市</area>
    <date>2022-04-02T15:30:14.175+08:00</date>
    <keys>
        <key>
            <roomNum>002</roomNum>
        </key>
        <key>
            <roomNum>001</roomNum>
        </key>
    </keys>
    <name>abc</name>
</human>

这样的date格式显然令人不满意,我们需要例如“2018-05-20”这样的格式。这就需要@XmlJavaTypeAdapter注解,自定义一个适配器来解决这个问题。该注解的用法就是自定义适配器并继承XmlAdapter类,实现里面的marshal和unmarshal方法,并在该注解上引用。修改例子:

自定义的DateAdapter:

package io.renren.modules.temptest;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author xubo
 * @ClassNme DateAdapter
 * @Description TODO
 * @Date 2022-04-02 15:33:18
 * @version1.0
 */
public class DateAdapter extends XmlAdapter<String, Date> {
    
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

//    1.格式化:Date -->String
//    String  format(Date date) 将Date格式化为日期/时间字符串
//    2.解析:String -->Date
//    Date parse(String source) 将符合格式的指定字符串转换为Date

    @Override
    public Date unmarshal(String v) throws Exception {
        return sdf.parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        return sdf.format(v);
    }
}

Person类:

@XmlJavaTypeAdapter(DateAdapter.class)
@XmlElement
public void setDate(Date date) {
    this.date = date;
}

生成的xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<human gender="男">
    <addr></addr>
    <area>林州市</area>
    <date>2022-04-02</date>
    <keys>
        <key>
            <roomNum>002</roomNum>
        </key>
        <key>
            <roomNum>001</roomNum>
        </key>
    </keys>
    <name>abc</name>
</human>

完美解决。

属性:

常用的就是value属性,其他属性请自行研究。

@XmlValue:

作用和用法:

字段和方法级别的注解。该注解的作用,简单理解就是定义xml元素文本值的类型,例如在一个类的String类型字段上使用该注解,则生成的元素文本值类型就是xsd:string,也就是定义一个xsd中的simpleType.若类中还有一个字段并使用了@XmlAttribute注解,则是定义一个xsd中的complexType。

属性:无

@XmlType:

作用和用法:

类级别的注解。该注解有些复杂,主要使用的是它的propOrder属性,简单来说是用来定义xsd中的simpleType或complexType,从生成的xml中来看,它的作用就是指定生成元素的顺序,具体看下图:

简单解释下每行什么意思:

* 若指定该注解的propOrder为{},会生成ComplexType并且使用xs:all指示器,表示所有被映射的元素都必须出现在xml中

* 若propOrder的值为{"name", "addr", "area"}(大括号中都是Person类的字段名称),会生成ComplexType并使用xs:sequence指示器,表示生成的xml元素必须按照propOrder指定的顺序出现,也就间接实现了排序。

* 若不指定propOrder属性(这与指定propOrder但值为{}不同),没有字段,会生成ComplexType并包含一个空的xs:sequence指示器。

* 若不指定propOrder属性,但含有被@XmlValue注解的字段和被@XmlAttribute注解的字段,会生成一个含有simpleContent的ComplexType。

* 若不指定propOrder属性,但含有被@XmlValue注解的字段而没有被@XmlAttribute注解的字段,会生成一个含有simpleType的ComplexType。

再次强调,如果以上解释看不懂,先学xsd。传送门:《XSD学习》

 

 

 

 

 
 
posted @ 2022-03-30 18:53  哩个啷个波  阅读(4414)  评论(4编辑  收藏  举报