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. 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法

    ==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...

  2. JAVA 实体类List<Entity >转 List<Map>

    public static <T extends IdEntity> List<Map<Object,Object>> EntityConvertMap(List& ...

  3. Qt学习笔记-安装phonon模块

    如果想要运行使用Qt中的phonon写的程序,需要满足一下条件:Qt基本库.Qt phonon库.phonon_backend(后端插件)和多媒体播放后台.下面以linux(Fedora 12)系统. ...

  4. offset()与position()的区别

    jQuery中有两个获取元素位置的方法offset()和position(),两者的定义如下: offset(): 获取匹配元素在当前视口的相对偏移. 返回的对象包含两个整形属性:top 和 left ...

  5. 学习 Gin 总结(2020.12.30-31)

    2020.12.30 问题总结 中间件 context.Next() 源码注释: // Next should be used only inside middleware. // It execut ...

  6. HTTP高级(Cookie,Session ,LocalStorage )

    Cookie 服务器通过 Set-Cookie 头给客户端一串字符串 客户端每次访问相同域名的网页时,必须带上这段字符串 客户端要在一段时间内保存这个Cookie Cookie 默认在用户关闭页面后就 ...

  7. 对于home主页的切换处理

    经过测试,发现,在home首页的时候,滑动到某一个位置的时候,如果再点击tabbar中的"购物车"."分类"或者"我的"的时候,再点击到首页 ...

  8. 通过python的socket库实现简易即时通讯小程序

    前言 最近学习了一下有关tcp协议和socket有关的知识,看到许多socket实战都喜欢教如何做一个聊天程序,于是想着试试能不能不看教程自己写一个.当然我没太多时间做一个像qq一样的ui界面,所以做 ...

  9. ARM CPU的SVC模式

    关于ARM CPU模式中的SVC Arm中CPU的模式 [第一方面] 系统sys模式 VS 管理svc模式 首先,sys模式和usr模式相比,所用的寄存器组,都是一样的,但是增加了一些访问一些在usr ...

  10. SICP 课程总结 & 复习

    SICP 课程总结 & 复习 小作文 有赖于那个终极的.伟大的.命定的教务系统,我选上了这门课:SICP,Structure and Interpret of Computer Program ...