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. windows下plsql连接linux下的oracle数据库

    windows下plsql连接linux下的oracle数据库 经过多方查找,终于找到解决办法,特此记录下来,共享之. PL/SQL Develorper:目前未发现可以在Linux系统中安装的版本. ...

  2. flowable获取上级主管

    //主管 Dept managerDept = deptUserUtil.getManagerDept(bean.getCreateDept(),bean.getCreateUser()); //上级 ...

  3. Idea利用maven创建web项目,并配置tomcat

    参考http://blog.csdn.net/myarrow/article/details/50824793#comments

  4. C语言实现汉诺塔

    汉诺塔 要把A柱子上的盘子移动到C柱子上,在移动过程中可以借助B柱子,但是要求小的盘子在上大的盘子在下. 解题思路: 1.把A柱子上的前N-1个盘子借助C柱子,全部移动到B柱子上(过程暂不考虑),再把 ...

  5. Linux内核源码分析之setup_arch (三)

    1. 前言 在 Linux内核源码分析之setup_arch (二) 中介绍了当前启动阶段的内存分配函数memblock_alloc,该内存分配函数在本篇将要介绍paging_init中用于页表和内存 ...

  6. Spring Boot 有哪些优点?

    a.减少开发,测试时间和努力. b.使用 JavaConfig 有助于避免使用 XML. c.避免大量的 Maven 导入和各种版本冲突. d.通过提供默认值快速开始开发.没有单独的 Web 服务器需 ...

  7. python之scrapy篇(二)

    一.创建工程 scarpy startproject xxx 二.编写iteam文件 # -*- coding: utf-8 -*- # Define here the models for your ...

  8. CF Grakn Forces 2020 1408E Avoid Rainbow Cycles(最小生成树)

    1408E Avoid Rainbow Cycles 概述 非常有趣的题目(指解法,不难,但很难想) 非常崇拜300iq,今天想做一套div1时看见了他出的这套题Grakn Forces 2020,就 ...

  9. promise引用自吕大豹

    去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ...

  10. 转载-notepad++ zend-coding使用

    转载-notepad++ zend-coding使用   zen-Coding是一款快速编写HTML,CSS(或其他格式化语言)代码的编辑器插件,这个插件可以用缩写方式完成大量重复的编码工作,是web ...