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);
    }
}

 

posted @ 2021-01-16 15:33  且行且码  阅读(2191)  评论(1编辑  收藏  举报