JAXB简单应用

1 篇文章 0 订阅

一、概述

        JAXB能够使用Jackson对JAXB注解的支持实现(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,可以更好进行JavaBean和xml、JSON直接的互相转换。JAXB允许Java人员将Java类映射为xml表示方式,常用的注解包括:@XmlRootElement,@XmlElement等等。

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

二、常用的注解

注解作用
@XmlType将Java类或枚举类型映射到XML模式类型
@XmlAccessorType(XmlAccessType.FIELD)控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标注)字段到XML。其他值还有XmlAccessType.PROPERTY和XmlAccessType.NONE
@XmlAccessorOrder控制JAXB 绑定类中属性和字段的排序
@XmlJavaTypeAdapter使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML
@XmlElementWrapper对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)
@XmlRootElement将Java类或枚举类型映射到XML元素
@XmlElement将Java类的一个属性映射到与属性同名的一个XML元素
@XmlAttribute

将Java类的一个属性映射到与属性同名的一个XML属性

三、数据类型绑定

AXB中XML数据类型和Java数据类型的映射关系

XML Schema类型

Java数据类型

xsd:string

java.lang.String

xsd:positiveInteger

java.math.BigInteger

xsd:int

int

xsd:long

long

xsd:short

short

xsd:decimal

java.math.BigDecimal

xsd:float

float

xsd:double

double

xsd:boolean

boolean

xsd:byte

byte

xsd:QName

javax.xml.namespace.QName

xsd:dateTime

javax.xml.datatype.XMLGregorianCalendar

xsd:base64Binary

byte[]

xsd:hexBinary

byte[]

xsd:unsignedInt

long

xsd:unsignedShort

int

xsd:unsignedByte

short

xsd:time

javax.xml.datatype.XMLGregorianCalendar

xsd:date

javax.xml.datatype.XMLGregorianCalendar

xsd:g

javax.xml.datatype.XMLGregorianCalendar

xsd:anySimpleType

java.lang.Object

xsd:anySimpleType

java.lang.String

xsd:duration

javax.xml.datatype.Duration

xsd:NOTATION

javax.xml.namespace.QName

四、使用示例

4.1 添加依赖

    <jaxb.version>4.0.1</jaxb.version>

    <!-- JAXB 依赖 -->
    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
        <version>${jaxb.version}</version>
        </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>${jaxb.version}</version>
    </dependency>

4.2 模型

import lombok.Getter;
import lombok.Setter;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import java.time.LocalDate;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"level", "cityName", "cityCode", "creationTime"})
@XmlRootElement(name = "Project")
@Getter
@Setter
public class CityXmlInfo {
    @XmlAttribute(name = "level")
    private String level = "";

    @XmlAttribute(name = "cityName ")
    private String cityName = "";

    @XmlAttribute(name = "cityCode ")
    private String cityCode = "";

    @XmlAttribute(name = "creationTime")
    private String creationTime = LocalDate.now().toString();
}
import java.util.List;

import lombok.Getter;
import lombok.Setter;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;

/**
 * JAXB测试模型 ProvincesXmlInfo
 *
 **/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"provinceXmlInfos"})
@XmlRootElement(name = "Provinces")
@Getter
@Setter
public class ProvincesXmlInfo {
    @XmlElement(name = "province", required = true)
    private List<ProvinceXmlInfo> provinceXmlInfos;
}
import lombok.Getter;
import lombok.Setter;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import java.time.LocalDate;
import java.util.List;

/**
 * JAXB测试模型 ProvinceXmlInfo
 *
 **/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"cityXmlInfo"})
@XmlRootElement(name = "Province")
@Getter
@Setter
public class ProvinceXmlInfo {
    @XmlAttribute(name = "level")
    private String level = "";

    @XmlAttribute(name = "provinceName")
    private String provinceName = "";

    @XmlAttribute(name = "provinceCode")
    private String provinceCode = "";

    @XmlAttribute(name = "creationTime")
    private String creationTime = LocalDate.now().toString();

    @XmlElement(name = "city", required = true)
    private List<CityXmlInfo> cityXmlInfo;
}

4.3 工具类

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;

import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 功能描述:Jaxb工具类
 *
 **/
@Slf4j
public class JaxbUtils {
    private static final String XML_FILE = ".xml";

    private JaxbUtils() {
    }

    /**
     * 将对象转为xml并写入{@code filePath}文件中, xml未格式化
     *
     * @param object   待转换写入的对象
     * @param filePath 待写入的文件路径
     * @param <T>      对象类型
     * @return 是否成功写入
     */
    public static <T> boolean marshal(T object, String filePath) {
        if (object == null) {
            return false;
        }
        OutputStream outputStream = null;
        BufferedOutputStream bos = null;
        XMLEventWriter xmlEventWriter = null;
        boolean marshalResult = true;
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.name());
            File file = new File(filePath);
            XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
            outputStream = org.apache.commons.io.FileUtils.openOutputStream(file);
            bos = new BufferedOutputStream(outputStream);
            xmlEventWriter = xmlOutputFactory.createXMLEventWriter(bos, StandardCharsets.UTF_8.name());
            marshaller.marshal(object, xmlEventWriter);
        } catch (Exception e) {
            log.error("{}", ExceptionUtils.getStackTrace(e));
            marshalResult = false;
        } finally {
            IoUtils.close(xmlEventWriter);
            IoUtils.close(bos, outputStream);
        }
        return marshalResult;
    }

    /**
     * 将对象转为xml字符,并格式化,然后写入{@code filePath}文件中
     *
     * @param object   待转换写入的对象
     * @param filePath 待写入的文件路径
     * @param <T>      对象类型
     * @return 是否成功写入
     */
    public static <T> boolean marshalAndFormat(T object, String filePath) {
        if (object == null) {
            return false;
        }
        FileOutputStream fos = null;
        boolean marshalResult = true;
        try {
            File file = new File(filePath);
            fos = org.apache.commons.io.FileUtils.openOutputStream(file);
            fos.write(objectConvertXml(object).getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            log.error("{}", ExceptionUtils.getStackTrace(e));
            marshalResult = false;
        } finally {
            IoUtils.close(fos);
        }
        return marshalResult;
    }

    /**
     * 将xml文件输入流,转换为Java对象
     *
     * @param inputStream 输入流
     * @param clazz       待转换的类
     * @param <T>         类型
     * @return 转换的对象
     */
    public static <T> Optional<T> xmlConvert2Object(InputStream inputStream, Class<T> clazz) {
        InputStreamReader inputStreamReader = null;
        Object obj = null;
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
            inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
            xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
            xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
            XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStreamReader);
            obj = unmarshaller.unmarshal(xmlStreamReader);
        } catch (Exception e) {
            log.warn("xmlConvert2Object fail, ", e);
        } finally {
            IoUtils.close(inputStreamReader);
            IoUtils.close(inputStream);
        }
        if (clazz.isInstance(obj)) {
            return Optional.of(clazz.cast(obj));
        }
        return Optional.empty();
    }

    /**
     * 将xml文件转换为Java对象
     *
     * @param filePath 待转换xml对象的xml文件路径
     * @param clazz    待转换的类
     * @param <T>      类型
     * @return 转换的对象
     */
    public static <T> Optional<T> xmlConvert2Object(String filePath, Class<T> clazz) {
        if (StringUtils.isEmpty(filePath)) {
            return Optional.empty();
        }
        if (!StringUtils.endsWithIgnoreCase(filePath, XML_FILE)) {
            return Optional.empty();
        }
        File file = new File(filePath);
        if (!file.exists()) {
            return Optional.empty();
        }
        try {
            InputStream inputStream = org.apache.commons.io.FileUtils.openInputStream(file);
            return xmlConvert2Object(inputStream, clazz);
        } catch (Exception e) {
            log.error("{}", ExceptionUtils.getStackTrace(e));
            return Optional.empty();
        }
    }

    private static <T> String objectConvertXml(T obj) {
        StringWriter sw = null;
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            sw = new StringWriter();
            marshaller.marshal(obj, sw);
            return sw.toString();
        } catch (Exception e) {
            log.error("{}", ExceptionUtils.getStackTrace(e));
            return StringUtils.EMPTY;
        } finally {
            IoUtils.close(sw);
        }
    }
}

4.4 单元测试

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;

import com.google.common.collect.Lists;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class JaxbUtilsTest {

    @Test
    void marshal() {
        ProvincesXmlInfo provincesXmlInfo = new ProvincesXmlInfo();
        ProvinceXmlInfo provinceXmlInfo = new ProvinceXmlInfo();
        provinceXmlInfo.setLevel("0");
        provinceXmlInfo.setProvinceCode("110000");
        provinceXmlInfo.setProvinceName("北京市");
        provinceXmlInfo.setCreationTime("2024-03-19");
        CityXmlInfo cityXmlInfo = new CityXmlInfo();
        cityXmlInfo.setCityCode("119900");
        cityXmlInfo.setCityName("市辖区");
        cityXmlInfo.setLevel("1");
        cityXmlInfo.setCreationTime("2024-03-19");
        List<CityXmlInfo> cityXmlInfos = Lists.newArrayList(cityXmlInfo);
        provinceXmlInfo.setCityXmlInfo(cityXmlInfos);
        provincesXmlInfo.setProvinceXmlInfos(Lists.newArrayList(provinceXmlInfo));
        boolean marshalSuccess = JaxbUtils.marshal(provincesXmlInfo, "src/test/resources/jaxb/marshal/marshal_province.xml");
        Assertions.assertTrue(marshalSuccess);
        File file = new File("src/test/resources/jaxb/marshal/marshal_province.xml");
        Assertions.assertTrue(file.exists());
    }

    @Test
    void marshalAndFormat() {
        ProvincesXmlInfo provincesXmlInfo = new ProvincesXmlInfo();
        ProvinceXmlInfo provinceXmlInfo = new ProvinceXmlInfo();
        provinceXmlInfo.setLevel("0");
        provinceXmlInfo.setProvinceCode("110000");
        provinceXmlInfo.setProvinceName("北京市");
        provinceXmlInfo.setCreationTime("2024-03-19");
        CityXmlInfo cityXmlInfo = new CityXmlInfo();
        cityXmlInfo.setCityCode("119900");
        cityXmlInfo.setCityName("市辖区");
        cityXmlInfo.setLevel("1");
        cityXmlInfo.setCreationTime("2024-03-19");
        List<CityXmlInfo> cityXmlInfos = Lists.newArrayList(cityXmlInfo);
        provinceXmlInfo.setCityXmlInfo(cityXmlInfos);
        provincesXmlInfo.setProvinceXmlInfos(Lists.newArrayList(provinceXmlInfo));
        boolean marshalSuccess =
            JaxbUtils.marshalAndFormat(provincesXmlInfo, "src/test/resources/jaxb/marshal/marshalAndFormat_province.xml");
        Assertions.assertTrue(marshalSuccess);
        File file = new File("src/test/resources/jaxb/marshal/marshalAndFormat_province.xml");
        Assertions.assertTrue(file.exists());
    }

    @Test
    void xmlConvert2Object() throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("src/test/resources/jaxb/marshal/marshalAndFormat_province.xml");
        Optional<ProvincesXmlInfo> optionalProvincesXmlInfo = JaxbUtils.xmlConvert2Object(inputStream, ProvincesXmlInfo.class);
        Assertions.assertTrue(optionalProvincesXmlInfo.isPresent());
        ProvincesXmlInfo provincesXmlInfo = optionalProvincesXmlInfo.get();
        Assertions.assertEquals(1, provincesXmlInfo.getProvinceXmlInfos().size());
        List<ProvinceXmlInfo> provinceXmlInfos = provincesXmlInfo.getProvinceXmlInfos();
        ProvinceXmlInfo provinceXmlInfo = provinceXmlInfos.getFirst();
        Assertions.assertEquals(1, provinceXmlInfo.getCityXmlInfo().size());
        Assertions.assertEquals("北京市", provinceXmlInfo.getProvinceName());
    }

    @Test
    void testXmlConvert2Object() {
        Optional<ProvincesXmlInfo> optionalProvincesXmlInfo =
            JaxbUtils.xmlConvert2Object("src/test/resources/jaxb/marshal/marshalAndFormat_province.xml", ProvincesXmlInfo.class);
        Assertions.assertTrue(optionalProvincesXmlInfo.isPresent());
        ProvincesXmlInfo provincesXmlInfo = optionalProvincesXmlInfo.get();
        Assertions.assertEquals(1, provincesXmlInfo.getProvinceXmlInfos().size());
        List<ProvinceXmlInfo> provinceXmlInfos = provincesXmlInfo.getProvinceXmlInfos();
        ProvinceXmlInfo provinceXmlInfo = provinceXmlInfos.getFirst();
        Assertions.assertEquals(1, provinceXmlInfo.getCityXmlInfo().size());
        Assertions.assertEquals("北京市", provinceXmlInfo.getProvinceName());
    }
}

测试结果

  • marshal_province.xml
<?xml version="1.0" encoding="UTF-8"?><Provinces><province level="0" provinceName="北京市" provinceCode="110000" creationTime="2024-03-19"><city level="1" cityName="市辖区" cityCode="119900" creationTime="2024-03-19"></city></province></Provinces>

  • marshalAndFormat_province.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Provinces>
    <province level="0" provinceName="北京市" provinceCode="110000" creationTime="2024-03-19">
        <city level="1" cityName="市辖区" cityCode="119900" creationTime="2024-03-19"/>
    </province>
</Provinces>
  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JAXB(Java Architecture for XML Binding)是一个Java API,它可以将XML文档与Java对象之间互相转换。下面是使用JAXB的步骤: 1. 创建Java类,这些类将用于表示XML文档中的元素和属性。 2. 使用JAXB提供的注解将Java类与XML元素和属性相映射。 3. 使用JAXB提供的Marshaller类将Java对象序列化为XML文档,或使用Unmarshaller将XML文档反序列化为Java对象。 4. 可以使用JAXB提供的工具生成Java类,这些类将与XML文档中的元素和属性相对应。 下面是一个例子,将Java对象序列化为XML文档: ```java @XmlRootElement public class Customer { private String name; private int age; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } public class Main { public static void main(String[] args) throws JAXBException { Customer customer = new Customer(); customer.setName("John"); customer.setAge(30); customer.setAddress("New York"); JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } } ``` 输出结果为: ```xml <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <address>New York</address> <age>30</age> <name>John</name> </customer> ``` 在上面的例子中,@XmlRootElement注解用于将Customer类与根元素相映射,@XmlElement注解用于将属性与XML元素相映射。创建JAXBContext和Marshaller对象后,可以使用marshal方法将Java对象序列化为XML文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值