JAXB学习(一):概述
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学习(一):概述的更多相关文章
- TCP/IP详解学习笔记- 概述
TCP/IP详解学习笔记(1)-- 概述1.TCP/IP的分层结构 网络协议通常分不同层次进行开发,每一层分别负责不同的同信功能.TCP/IP通常被认为是一个四层协议系统. 如图所 ...
- Unity基础学习-Unity概述
Unity 概述 Unity是一个强大的引擎,里面包括大量的工具用来满足各种各样的需求.Unity的编辑器是直观的可定制的,让您在您的工作流中有较大的自由度. 本小节是开始学习Unity的关键部分.里 ...
- STM32单片机学习心得——概述
我校的课程真是跟不上时代发展,甚至还在教授8051/8052单片机的内容,于是不甘寂寞的我就自己踏入了STM32单片机的坑-- 首先,我现在大二,刚学完模拟电子技术,还没有学习数字电路技术,于是自学单 ...
- java web jsp学习笔记--概述-常用语法,指令,动作元素,隐式对象,域对象
JSP学习笔记 1.什么是jsp JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.JSP/Servlet规范.JS ...
- Java IO学习--(一)概述
在这一小节,我会试着给出Java IO(java.io)包下所有类的概述.更具体地说,我会根据类的用途对类进行分组.这个分组将会使你在未来的工作中,进行类的用途判定时,或者是为某个特定用途选择类时变得 ...
- AI学习--机器学习概述
学习框架 01-人工智能概述 机器学习.人工智能与深度学习的关系 达特茅斯会议-人工智能的起点 机器学习是人工智能的一个实现途径深度学习是机器学习的一个方法发展而来(人工神经网络) 从图上可以看出,人 ...
- 大数据技术之_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 ...
- TCP/IP协议学习-1.概述
目录 TCP/IP协议概述 分层 延伸知识 FTP例子 为什么需要网络层和传输层 TCP/IP的分层 封装 分用 总结 本文主要摘抄自书籍<TCP/IP详解卷一:协议>与TCP协议相关内容 ...
- 《Pro Express.js》学习笔记——概述
要学Node.js,先学Express.js. Express.js是Node.js官方推荐的基础框架. Express.js框架经过一系列的发展,已经到了4.x版本.新的版本解决了3.x之前版本的依 ...
随机推荐
- 讲两个int 数组找出重复的数字 用最少的循环
int a[] = {1,3}; int b[] = {1,3,5}; int size = a.length>b.length ?a.length:b.length; int valueA = ...
- 使用pdf.js aspose各种文档转PDF 版本对应license.xml 去水印破解
在使用pdf.js途中,使用aspose转换的文件一直有水印,在网上找了许多破解办法都是已经失效的,于是乎,就查看了一下jar的源码,找到了版本对应的破解字符(如下):对应版本为 aspose-wor ...
- redis系列:分布式锁
redis系列:分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 笔记本使用网线连接可以进行ftp下载,但是通过wifi连接只能登陆不能下载的问题。
环境: (1)服务器为阿里云服务器,有公网ip,有内网ip,公网和内网已经做了相关端口的映射,ftp服务器为FileZilla,ftp服务器被动模式已开启,防火墙已关闭 (2)ftp客户端为java写 ...
- 日常入坑1-Calendar类
1.当前时间是一号的时候,通过计算上一天的日期的时候,需要注意了 Calendar calendar = Calendar.getInstance();calendar.set(2019,10,1); ...
- linux 下socket编程
原理 类unix系统中, 一切皆文件, 诸如磁盘文件, 显卡, 内核驱动, 网络协议栈等 socket就是linux中提供的用于网络通信的文件接口, 两台机器之间可以读写消息 在使用socket真正的 ...
- php 二位数组 转一维数组
$result = []; array_map(function ($value) use (&$result) { $result = array_merge($result, array_ ...
- 【Flutter】可滚动组件之ListView
前言 它可以沿一个方向线性排布所有子组件,并且它也可以支持基于Sliver的延迟构建模型. 接口描述 ListView({ Key key, // 可滚动widget公共参数 Axis scrollD ...
- load data local带来的安全问题
load data默认读的是服务器上的文件,但是加上local参数后,就可以将本地具有访问权限的文件加载到数据库中,这在带来方便的同时,也带来了以下安全问题, 可以任意加载本地文件到数据库, 在web ...
- Over Permission - Pikachu
概述: 如果使用A用户的权限去操作B用户的数据,A的权限小于B的权限,如果能够成功操作,则称之为越权操作. 越权漏洞形成的原因是后台使用了不合理的权限校验规则导致的. 一般越权漏洞容易出现在权限页面( ...