java-jaxb学习实践

本篇博客为学习笔记。通过学习网上博客总结而作,文字描述部分是总结,代码部分经过学习修改,运行通过。

JAXB,是JavaEE的规范,全称Java Architecture for XML Binding。

它是一种可以根据XML Schema产生Java类的技术,JAXB也提供将XML实例文档反向生成java对象树的方法,并将java对象树的内容重新写入XML实例文档。

1.1 java对象与xml互转场景

2. 引入JAXB包

在项目管理文件pom.xml里面,引入jaxb的jar包

    <!-- http://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core -->
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-core</artifactId>
      <version>2.2.11</version>
    </dependency>
    <!-- http://mvnrepository.com/artifact/javax.xml/jaxb-api -->
    <dependency>
      <groupId>javax.xml</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.1</version>
    </dependency>
    <!-- http://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl -->
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>2.2.11</version>
    </dependency>

3. 使用JAXB包

引入了JAXB的包以后,便可以在自己的类上面,使用JAXB提供的类,接口,注解等。

3.1 将java对象转换为XML

package com.liwl.dev;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class LiwanLiangJAXB {

   String name;
   int age; 
   int id;

   public String getName() {
       return name;
   }

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

   public int getAge() {
       return age;
   }

   @XmlElement
   public void setAge(int age) {
       this.age = age;
   }

   public int getId() {
       return id;
   }

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

   @Override
   public String toString(){
       return "LiwanLiangJAXB [name=" + name + ",age=" + age + ",;
   }
};

测试程序代码:

package com.liwl.dev;

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

public class MyTest {
    public static void main(String[] args) {
        LiwlJAXBMarshall liwljaxb = new LiwlJAXBMarshall();
        liwljaxb.setName("liwanliang");
        liwljaxb.setAge(30);
        liwljaxb.setId(100);
        try {
            File file = new File("/tmp/liwl.xml");//这里产生一个file.xml文件
            JAXBContext jaxbContext = JAXBContext.newInstance(LiwlJAXBMarshall.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
            jaxbMarshaller.marshal(liwljaxb, file);
            jaxbMarshaller.marshal(liwljaxb, System.out);
        } catch (JAXBException e) {
            e.printStackTrace();
        }   
    }
}

产生的file.xml内容如下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<liwlJAXBMarshall>
    <age>30</age>
    <id>100</id>
    <name>liwanliang</name>
</liwlJAXBMarshall>

3.2 将XML转为java对象

将上面代码产生的/tmp/file.xml,拷贝为/tmp/liwl.xml,然后通过代码读出。如下:

import javax.xml.bind.Unmarshaller;
...
public class MyTest {
    public static void main(String[] args) {

        LiwlJAXBMarshall liwljaxb = new LiwlJAXBMarshall();
        liwljaxb.setName("liwanliang");
        liwljaxb.setAge(30);
        liwljaxb.setId(100);
        try {
            File file = new File("/tmp/liwl.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(LiwlJAXBMarshall.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            LiwlJAXBMarshall liwl = (LiwlJAXBMarshall) jaxbUnmarshaller.unmarshal(file);
            System.out.println(liwl);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

4. JAXB相关注解解释

本部分内容摘抄于《Jaxb完全手册》,总结归纳。

JAXBContent类,是应用的入口,用于管理XML/Java绑定信息

Marshaller接口,将java对象序列化为XML数据

Unmarshaller接口,将XML数据反序列化为java对象

@XmlType

用在class的注解。常与@XmlRootElement,@XmlAccessorType一起用。它有三个属性

  • name
  • propOrder
  • namespace

常用前2个属性。

如果同时使用了@XmlType(propOrder={})和@XmlAccessOrder(XmlAccessOrder.ALPHABETICAL)时候,生成的xml只按照propOrder定义的顺序,其具有优先权。

注意:在使用该注解的propOrder属性时,必须列出javaBean对象的所有属性,否则会报错

@XmlType(name="xxx",propOrder={
    "xxx",
    "yyy",
    "zzz"
})

@XmlRootElement

用于类级别的注解,对应xml的根元素。常与@XmlType和@XmlAccessorType一起用。

@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Liwl{
}

@XmlElement

将java对象的属性,映射为xml节点。在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。

@XmlElement(name="Address")
privage String yourAddress

@XmlElementWrapper

@XmlAttribute

把java对象的属性,映射为xml的属性,并可通过name属性,为生成的xml属性指定别名。

@XmlAttribute(name="Country")
private String state;

@XmlAccessorType

用于指定由java对象生成xml文件时,对java对象属性访问的方式。常与@XmlRootElement和@XmlType一起使用。

其属性是XmlAccessType的4个枚举值,分别为:

  • XmlAccessType.FIELD java对象中所有成员的变量
  • XmlAccessType.PROPERTY java对象中所有通过getter/setter方式访问的成员变量
  • XmlAccessType.PUBLIC_MEMBER java对象中所有的public访问权限成员变量和通过getter/setter方式访问的成员变量
  • XmlAccessType.NONE java对象的所有属性都不映射为xml的元素

注意:

  • @XmlAccessorType默认的访问级别是XmlAccessType.PUBLIC_MEMBER。因此:如果java对象中的private成员变量,设置了具有public权限的getter/setter方法,就不要在private变量上面使用@XmlElement和@XmlAttribute注解,否则由java对象生成xml时,会报【同一个属性在java类里面存在两次的错误】。同理:如果@XmlAccessorType的访问权限为XmlAccessType.NONE,如果在java成员变量使用了@XmlElement或@XmlAttriute注解,这些成员变量依然可以映射到xml文件
  • 虽然@XmlAccessorType为@XmlAccessType.NONE,但是在java类的私有属性加上@XmlAttribute和@XmlElement注解后,这些私有成员会映射成xml元素

@XmlAccessorOrder

该注解对java对象生成的xml元素排序,它有两个属性值:

  • AccessorOrder.ALPHABETICAL 对生成的xml元素按照字母书写顺序排序
  • XmlAccessOrder.UNDEFINED 不排序

@XmlTransient

该注解用于标注由java对象映射xml时,忽略被此注解标注的属性。即在生成的文件中不出现此元素

@XmlJavaTypeAdapter

常用于在转换比较复杂的对象时,如map类型或者格式化日期等,使用此注解,需要自己写一个adapter类继承XmlAdapter抽象类,并实现里面的方法。

@XmlJavaTypeAdapter(value=xxx.class),value为自己定义的adapter类

5. 参考博客

《JAXB简单样例》

《Jaxb完全手册》