pre.XML { background-color: rgba(255, 204, 204, 1); padding-left: 25px }

JAXB是 Java Architecture for XML Binding的首字母缩写,它是一个处理XML文档的易用框架。 与之前的处理方式(比如DOM解析)相比,它的优势在于能够将XML文档直接与java对象绑定,包括序列化(java ->xml)和反序列化(xml -> java),而DOM解析仅仅能够得到一个string类型的节点树,我们可以把jaxb理解为能够对象化处理XML的工具。  就像ORM能够将数据库记录映射为JAVA对象一样,JAXB将XML元素映射为JAVA对象。

我们有两种方式来获得描述节点信息的java类型,一种是写一个XML schema,它们通常是使用 W3C XML Schema Language 写成的(*.xsd),然后使用 jdk的 xjc 实用工具编译这个xsd文件,就可以生成我们需要的一系列java文件了。 第二种方法是我们自己手动编写需要的java文件,其实所需要的都是一些基本的POJO类,我们需要做的只不过是给他们加上JAXB所支持的相应的annotation而已。 这两种方式本质上是一样的,我们手动编写的java文件基本等同于 xjc 实用工具生成的文件。

关于JAXB的第一种方式,不在本文的讨论范围内, 可以参考 JAXB Tutorial ,本文的绝大多数内容也都可以从这个教程中找到。

下面我们展示一个JAXB的简单示例,以期能对JAXB有一个具体的认识。

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {
private String name;
private int age; 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;
}
}

上面的这个java类实在不能再简单了,唯一值得注意的是它有一个 @XmlRootElement 类注解。下面我们就使用JAXB来对这个POJO类进行XML的序列化(marshal)和反序列化(unmarshal)。

import java.io.FileInputStream;
import java.io.FileOutputStream; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller; public class MarshallerTest {
public static void main(String[] args) throws JAXBException {
marshall(); unMarshal();
} public static void marshall() throws JAXBException{
Person person = new Person();
person.setName("Zhangsan");
person.setAge(11); JAXBContext context = JAXBContext.newInstance(Person.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //将XML打印到控制台
marshaller.marshal(person, System.out); //将XML输出到一个文件,以便后面进行反序列化
try(FileOutputStream out = new FileOutputStream("C:/temp/person.xml")){
marshaller.marshal(person, out);
}catch(Exception e){
e.printStackTrace();
}
} public static void unMarshal() throws JAXBException{
JAXBContext context = JAXBContext.newInstance(Person.class);
Unmarshaller u = context.createUnmarshaller(); try(FileInputStream in = new FileInputStream("C:/temp/person.xml")){
Person person = (Person)u.unmarshal(in);
System.out.println(person.getName() + " : " + person.getAge());
}catch(Exception e){
e.printStackTrace();
}
}
}

生成的XML内容为:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<age>11</age>
<name>Zhangsan</name>
</person>

序列化和反序列化的步骤

无论序列化还是反序列化第一个需要获得的就是JAXBContext对象,它提供了JAXB API 的入口,我们使用JAXBContext.newInstance静态方法来获得它,问题在于需要传入的参数。

我们在前面提到过使用JAXB有两种方式: 1. 编写XML Schema,然后使用xjc实用工具编译。 2. 手动编写pojo,使用特定注解修饰。 他们获得JAXBContext的方式会稍微不同,我们仅仅考虑第二种情况。

在手动编写java 代码的情况中,我们有两种方式来获得JAXBContext:

1. 传入所有需要被JAXB处理的类的class对象。 通常情况下,顶层元素就足够了,因为JAXB将会从顶层元素开始递归引用到 顶层元素涉及到的类型(比如实例变量的类型),但是顶层元素的子类是不会被JAXB处理到的。

在下面的例子中我们定义了三个pojo:Person 、Dog 和LittleDog, 他们都被XmlRootElement所修饰,其中LittleDog是Dog的子类, 而Person被Dog所引用。

@XmlRootElement
public class Person {
public String name = "zhangsan";
} @XmlRootElement
public class Dog {
public String size = "big";
public Person owner = new Person();
} @XmlRootElement
public class LittleDog extends Dog{
public int age = 11;
}

我们在创建JAXBContext的时候,如果仅仅传入Dog.class,那么Dog和Person会被JAXB处理,而LittleDog则不会,如果我们使用JAXB处理LittleDog,那么它会被当成Dog来处理。

    public static void main(String[] args) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(new Person(), System.out);
marshaller.marshal(new LittleDog(), System.out);
}

上面的序列化结果为:

<!-- 下面是Person对象的序列化结果,因为Person被Dog引用,所以也被JAXB处理了 -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<name>zhangsan</name>
</person> <!-- 注意下面是LittleDog的序列化结果,很显然它仅仅被当做一个Dog对象处理了-->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dog>
<size>big</size>
<owner>
<name>zhangsan</name>
</owner>
</dog>

我们除了明确的把LittleDog.class也传入到JAXBContext.newInstance方法中去外,还可以使用@XmlSeeAlso,如下:

@XmlRootElement
//XmlSeeAlso的含义就是说当JAXB处理Dog的时候也处理哪些类型
@XmlSeeAlso({LittleDog.class})
public class Dog {
public String size = "big";
public Person owner = new Person();
}

2. 如果在一个包中定义了一个jaxb.index文件,并在其中声明了需要被JAXB处理的类型,那么我们可以将这个包名传递进来。还是接着上面的例子,我们可以这样定义jaxb.index文件

Dog
LittleDog

这样Dog Person和LittleDog就都可以被JAXB所处理了。这种情况适合于在同一个包中有好多没有引用关系的类的情况。 另外注意 格式为 "ClassName" 或 "OuterClass.InnerClass", 而不是 "ClassName.class" 或 "fully.qualified.ClassName" 。

在获得到JAXBContext之后,我们就可以得到试用createMarshaller和createUnmarshaller分别创建序列化和反序列化对象了。 而真正的序列化和反序列化无非就是将数据写入流中和从流中读取而已。

在下一篇文章中,我们将学习关于JAXB annotation的具体应用。

JAXB学习(一):概述的更多相关文章

  1. TCP/IP详解学习笔记- 概述

    TCP/IP详解学习笔记(1)-- 概述1.TCP/IP的分层结构      网络协议通常分不同层次进行开发,每一层分别负责不同的同信功能.TCP/IP通常被认为是一个四层协议系统.      如图所 ...

  2. Unity基础学习-Unity概述

    Unity 概述 Unity是一个强大的引擎,里面包括大量的工具用来满足各种各样的需求.Unity的编辑器是直观的可定制的,让您在您的工作流中有较大的自由度. 本小节是开始学习Unity的关键部分.里 ...

  3. STM32单片机学习心得——概述

    我校的课程真是跟不上时代发展,甚至还在教授8051/8052单片机的内容,于是不甘寂寞的我就自己踏入了STM32单片机的坑-- 首先,我现在大二,刚学完模拟电子技术,还没有学习数字电路技术,于是自学单 ...

  4. java web jsp学习笔记--概述-常用语法,指令,动作元素,隐式对象,域对象

     JSP学习笔记 1.什么是jsp JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.JSP/Servlet规范.JS ...

  5. Java IO学习--(一)概述

    在这一小节,我会试着给出Java IO(java.io)包下所有类的概述.更具体地说,我会根据类的用途对类进行分组.这个分组将会使你在未来的工作中,进行类的用途判定时,或者是为某个特定用途选择类时变得 ...

  6. AI学习--机器学习概述

    学习框架 01-人工智能概述 机器学习.人工智能与深度学习的关系 达特茅斯会议-人工智能的起点 机器学习是人工智能的一个实现途径深度学习是机器学习的一个方法发展而来(人工神经网络) 从图上可以看出,人 ...

  7. 大数据技术之_09_Flume学习_Flume概述+Flume快速入门+Flume企业开发案例+Flume监控之Ganglia+Flume高级之自定义MySQLSource+Flume企业真实面试题(重点)

    第1章 Flume概述1.1 Flume定义1.2 Flume组成架构1.2.1 Agent1.2.2 Source1.2.3 Channel1.2.4 Sink1.2.5 Event1.3 Flum ...

  8. TCP/IP协议学习-1.概述

    目录 TCP/IP协议概述 分层 延伸知识 FTP例子 为什么需要网络层和传输层 TCP/IP的分层 封装 分用 总结 本文主要摘抄自书籍<TCP/IP详解卷一:协议>与TCP协议相关内容 ...

  9. 《Pro Express.js》学习笔记——概述

    要学Node.js,先学Express.js. Express.js是Node.js官方推荐的基础框架. Express.js框架经过一系列的发展,已经到了4.x版本.新的版本解决了3.x之前版本的依 ...

随机推荐

  1. java 去掉html标签 使用正则表达式删除HTML标签。

    import java.util.regex.Matcher; import java.util.regex.Pattern; public class HTMLSpirit{ public stat ...

  2. Group by后加rollup、cube、Grouping_Sets的用法区别

    一.相关分析 通常当聚合率和数据量没有大于一定程度时,对于不涉及Rollup.Cube.Grouping_Sets这三种操作的聚合很少出现GC问题.对于Rollup.Cube.Grouping_Set ...

  3. Study_way

    一.Study 学习通Java基础视频.语法 开源中国 (Git)版本控制 读懂程序.源代码 相关资源 百度网盘 程序:方法(数学) 二.参数传递 基本数据的传参:虚参改变影响实参 引用数据的传参:数 ...

  4. 用python做youtube自动化下载器 代码

    目录 项目地址 思路 流程 1. post i. 先把post中的headers格式化 ii.然后把参数也格式化 iii. 最后再执行requests库的post请求 iv. 封装成一个函数 2. 调 ...

  5. 【JavaWeb】i18n 国际化

    i18n 国际化 什么是 i18n 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问. 希望相同的一个网站,不同人访问的时候 ...

  6. 隐马尔科夫模型(HMM)原理详解

    隐马尔可夫模型(Hidden Markov Model,HMM)是可用于标注问题的统计学习模型,描述由隐藏的马尔可夫链随机生成观测序列的过程,属于生成模型.HMM在语音识别.自然语言处理.生物信息.模 ...

  7. Mac配置jmeter环境变量

    #JAVA_HOME#JMETER_HOMEexport JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents ...

  8. JAR冲突问题的解决以及运行状态下如何查看加载的类

    今天碰到群里小伙伴问,线上程序好像有多个不同版本的Netty包,怎么去看到底加载了哪一个? 在说如何看之前,先来说说,当你开始意识到项目里有多个不同版本的Jar包,都是因为遇到了这几个异常: java ...

  9. scp传文件夹

    scp -r /root/backupdb/2014-08-15(文件夹)    root@192.168.1.98:/root(目录)

  10. 【MySQL】CentOS7中使用systemctl工具管理启动和停止MySQL

    centos7以前版本,可以使用这个/etc/init.d/mysqld start 来启动mysql 但是centos7之后,通过systemctl start mysqld.service 这个要 ...