Jaxb 完全手册
Jaxb是JavaEE的规范.全称Java Architecture for XML Binding.
可以根据XML Schema产生Java类的技术.JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档.
JAXB 2.0是JDK 1.6的组成部分。JAXB 2.2.3是JDK 1.7的组成部分。在实际使用不需要引入新的jar.
我一般使用都是配合JPA使用,下面例子也是按JPA+JAXB来说明.
因此我需要引入jpa的实现包.hibernate-validator随便.做验证用的.
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.1.Final</version>
</dependency>
1. JDK中JAXB相关的重要Class和Interface:
- JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。
- Marshaller接口,将Java对象序列化为XML数据。
- Unmarshaller接口,将XML数据反序列化为Java对象。
http://my.oschina.net/zhaoqian/blog/89763 这个是简单的入门demo.可以先运行试试,对JAXB有个大概的使用方法.下面例子将是系统正常做的.并对并发性进行处理的一个例子.
2. 常用注解说明
常用的annotation有:
@XmlType
@XmlElement
@XmlRootElement
@XmlAttribute
@XmlAccessorType
@XmlAccessorOrder
@XmlTransient
@XmlJavaTypeAdapter
@Temporal(TemporalType.XXXX) -->JPA中的时间处理注解,非JAXB
@XmlElementWrapper
1.@XmlType
@XmlType用在class类的注解,常与@XmlRootElement,@XmlAccessorType一起使用。它有三个属性:name、propOrder、namespace,经常使用的只有前两个属性。如:
同时使用了@XmlType(propOrder={})和@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)的时候,生成的xml只按照propOrder定义的顺序生成元素
@XmlType(name = "basicStruct", propOrder = {
"intValue",
"stringArray",
"stringValue"
)
在使用@XmlType的propOrder 属性时,必须列出JavaBean对象中的所有属性,否则会报错。
2.@XmlRootElement
@XmlRootElement用于类级别的注解,对应xml的跟元素,常与 @XmlType 和 @XmlAccessorType一起使用。如:
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Address {}
3.@XmlElement
@XmlElement将java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。如:
@XmlElement(name="Address")
private String yourAddress;
4.@XmlAttribute
@XmlAttribute用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。如:
@XmlAttribute(name="Country")
private String state;
5.@XmlAccessorType
@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或@XmlAttribute注解,这些成员变量依然可以映射到xml文件。
注意:虽然@XmlAccessorType为XmlAccessType.NONE,但是在java类的私有属性上加了@XmlAttribute和@XmlElement注解后,这些私有成员会映射生成xml的元素
6.@XmlAccessorOrder
@XmlAccessorOrder用于对java对象生成的xml元素进行排序。它有两个属性值:
AccessorOrder.ALPHABETICAL:对生成的xml元素按字母书序排序
XmlAccessOrder.UNDEFINED:不排序
7.@XmlTransient
@XmlTransient用于标示在由java对象映射xml时,忽略此属性。即,在生成的xml文件中不出现此元素。
8.@XmlJavaTypeAdapter
@XmlJavaTypeAdapter常用在转换比较复杂的对象时,如map类型或者格式化日期等。使用此注解时,需要自己写一个adapter类继承XmlAdapter抽象类,并实现里面的方法。
@XmlJavaTypeAdapter(value=xxx.class),value为自己定义的adapter类
XmlAdapter 抽象接口如下:
public abstract class XmlAdapter<ValueType,BoundType> { // Do-nothing constructor for the derived classes.
protected XmlAdapter() {}
// Convert a value type to a bound type.
public abstract BoundType unmarshal(ValueType v);
// Convert a bound type to a value type.
public abstract ValueType marshal(BoundType v);
}
实际案例:
<i>package jaxb.shop; import java.util.Date;
import java.text.SimpleDateFormat; import javax.xml.bind.annotation.adapters.XmlAdapter; public class DateAdapter extends XmlAdapter<String, Date> { private String pattern = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat fmt = new SimpleDateFormat(pattern); @Override
public Date unmarshal(String dateStr) throws Exception { return fmt.parse(dateStr);
} @Override
public String marshal(Date date) throws Exception { return fmt.format(date);
} }
//用于格式化日期在xml中的显示格式,并且由xml unmarshal为java对象时,将字符串解析为Date对象</i>
在某个类中如下使用,解析出对应的时间格式.必须重载那2个方法,用于JAXB marshal xml,xml unmarshal object时候使用.
@XmlJavaTypeAdapter(value=DateAdapter.class)
private Date purDate;
9.但如果是和JPA一起使用的话,可以使用@Temporal(TemporalType.DATE)来格式时间,默认为TemporalType.TIMESTAMP类型.TemporalType属性如下:
public enum TemporalType {
DATE, //java.sql.Date
TIME, //java.sql.Time
TIMESTAMP //java.sql.Timestamp
}
java.sql.Date
日期型,精确到年月日,例如“2008-08-08”
java.sql.Time
时间型,精确到时分秒,例如“20:00:00”
java.sql.Timestamp
时间戳,精确到纳秒,例如“2008-08-08 20:00:00.000000001”
10.在JAXB标准中,@XmlElementWrapper注解表示生成一个包装 XML 表示形式的包装器元素。 此元素主要用于生成一个包装集合的包装器 XML 元素。
注:@XmlElementWrapper仅允许出现在集合属性上。最后的案例将使用这个注解.
3. 最终案例(模拟XML--系统 --DB)
例子XML示例.
<?xml version="1.0" encoding="utf-8"?>
<userinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<id>110</id>
<name>Credo</name>
<address>China BeiJing</address>
<job>programmer</job>
<overinfos>
<overinfo>
<hobby>Accompany my girlfriend.</hobby>
<!--开始日期 dateTime-->
<beginDate>2009-06-02T12:00:00</beginDate>
<!--结束日期 dateTime-->
<endDate>2109-06-02T12:00:00</endDate>
</overinfo>
<overinfo>
<hobby>Write some code.</hobby>
<!--开始日期 dateTime-->
<beginDate>2009-06-02T12:00:00</beginDate>
<!--结束日期 dateTime-->
<endDate>2029-06-02T12:00:00</endDate>
</overinfo>
</overinfos>
</userinfo>
Model层(JAXB+JPA):
package org.credo.jaxb.model;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import org.hibernate.validator.constraints.Length;
/**
* @author Credo
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
@Table(name = "USERINFO")
public class Userinfo implements Serializable{ private static final long serialVersionUID = 7870351249722416047L; @Id
@Column(name = "ID", nullable = false)
private Long id; @Column(name = "NAME", length = 50)
@Length(max = 50)
private String name; @Column(name = "ADDRESS", length = 50)
@Length(max = 50)
private String address; @Column(name = "JOB", length = 50)
@Length(max = 50)
private String job; @XmlElementWrapper(name = "overinfos")
@OneToMany(cascade = CascadeType.ALL)
@XmlElements(value = { @XmlElement(name = "overinfo", type = Overinfo.class) })
private List<Overinfo> overinfos; public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public List<Overinfo> getOverinfos() {
return overinfos;
}
public void setOverinfos(List<Overinfo> overinfos) {
this.overinfos = overinfos;
} }
Overinfo.class
package org.credo.jaxb.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "overinfo")
@Entity
@Table(name = "OVERINFO")
public class Overinfo implements Serializable {
private static final long serialVersionUID = 2579971237985854291L;
@XmlTransient
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id; @XmlTransient
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "UserinfoId")
private Userinfo userinfo; @Column(name = "hobby", length = 20)
private String hobby; @Temporal(TemporalType.DATE)
@Column(name = "beginDate", length = 20)
private Date beginDate; @Temporal(TemporalType.DATE)
@Column(name = "endDate", length = 20)
private Date endDate;
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Userinfo getUserinfo() {
return userinfo;
}
public void setUserinfo(Userinfo userinfo) {
this.userinfo = userinfo;
}
}
JAXB并发处理:
package org.credo.jaxb;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
public final class JAXBCache {
private static final JAXBCache instance = new JAXBCache();
private final ConcurrentMap<String, JAXBContext> contextCache = new ConcurrentHashMap<String, JAXBContext>();
private JAXBCache() {
}
public static JAXBCache instance() {
return instance;
}
JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {
JAXBContext context = contextCache.get(clazz.getName());
if ( context == null )
{
context = JAXBContext.newInstance(clazz);
contextCache.putIfAbsent(clazz.getName(), context);
}
return context;
}
}
JAXBExportSchema 导出JAXB的 class的 结构
package org.credo.jaxb;
import java.io.File;
import java.io.IOException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import org.credo.jaxb.model.Userinfo;
/**
* JAXB 导出Schema。
*
* @author: Credo
* @date: 2013-6-25
*/
public class JAXBExportSchema {
public static void main(String[] args) {
JAXBContext jct;
try
{
jct = JAXBContext.newInstance(Userinfo.class);
jct.generateSchema(new Resolver());
}
catch ( Exception ex )
{
ex.printStackTrace();
}
}
}
class Resolver extends SchemaOutputResolver {
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
File file = new File("d:\\", suggestedFileName);
StreamResult result = new StreamResult(file);
result.setSystemId(file.toURI().toURL().toString());
return result;
}
}
JAXBUtil以及main方法测试:
package org.credo.jaxb;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.apache.commons.io.IOUtils;
import org.credo.jaxb.model.Overinfo;
import org.credo.jaxb.model.Userinfo;
/**
* marshal对象和unmarshal对象都是由JAXBContext创建.所以一开始需要初始化JAXBContext.
* @author Credo
*/
public class JAXBUtil {
/**
* 生成xml文件的二进制数据
* @param obj 对象
*/
public static byte[] marshal(Object obj) throws JAXBException {
JAXBContext context = JAXBCache.instance().getJAXBContext(obj.getClass());
Marshaller m = context.createMarshaller();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(obj, outputStream);
byte[] result = outputStream.toByteArray();
return result;
}
/**
* @param data xml stream
* @param classe 类
* @return jaxb生成xml的java 类对象
*/
public static Object unmarshal(byte[] data, Class<?> classe) throws JAXBException {
JAXBContext context = JAXBCache.instance().getJAXBContext(classe);
Unmarshaller m = context.createUnmarshaller();
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
Object obj = m.unmarshal(inputStream);
return obj;
}
/**
* @param data xml stream
* @param classe 类
* @return jaxb生成xml的java 类对象
*/
public static Object unmarshal(InputStream in, Class<?> classe) throws JAXBException, IOException {
JAXBContext context = JAXBCache.instance().getJAXBContext(classe);
byte[] data = IOUtils.toByteArray(in);
Unmarshaller m = context.createUnmarshaller();
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
Object obj = m.unmarshal(inputStream);
return obj;
}
public static void main(String[] args) throws JAXBException {
Userinfo userinfo = new Userinfo();
userinfo.setId(Long.valueOf(11));
List<Overinfo> list = new ArrayList<Overinfo>();
Overinfo e = new Overinfo();
e.setHobby("陪女友");
list.add(e);
Overinfo e1 = new Overinfo();
e1.setHobby("写代码");
list.add(e1);
userinfo.setOverinfos(list);
byte[] b = JAXBUtil.marshal(userinfo);
System.out.println(new String(b));
userinfo = (Userinfo) JAXBUtil.unmarshal(b, Userinfo.class);
System.out.println(userinfo.getOverinfos().get(0).getHobby());
}
}
就不说明了,仔细看代码的,一会就明白了.不看的运行下也明白了.下面是上面main方法测试的输出结果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<userinfo>
<id>11</id>
<overinfos>
<overinfo>
<hobby>陪女友</hobby>
</overinfo>
<overinfo>
<hobby>写代码</hobby>
</overinfo>
</overinfos>
</userinfo>
陪女友
下面是使用JAXBExportSchema 导出JAXB的 class的 结构
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="userinfo" type="userinfo"/>
<xs:complexType name="userinfo">
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
<xs:element name="address" type="xs:string" minOccurs="0"/>
<xs:element name="job" type="xs:string" minOccurs="0"/>
<xs:element name="overinfos" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="overinfo" type="overinfo" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="overinfo">
<xs:sequence>
<xs:element name="hobby" type="xs:string" minOccurs="0"/>
<xs:element name="beginDate" type="xs:dateTime" minOccurs="0"/>
<xs:element name="endDate" type="xs:dateTime" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Jaxb 完全手册的更多相关文章
- java注释指导手册
译文出处: Toien Liu 原文出处:Dani Buiza 编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 我们已经在Java Code Geeks提供了丰富 ...
- Java 注解指导手册 – 终极向导
原文链接 原文作者:Dani Buiza 译者:Toien Liu 校对:深海 编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 我们已经在Java Code Gee ...
- Java 注解指导手册(下)
9. 自定义注解 正如我们之前多次提及的,可以定义和实现自定义注解.本章我们即将探讨. 首先,定义一个注解: public @interface CustomAnnotationClass ...
- Java 注解指导手册(上)
编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 我们已经在Java Code Geeks提供了丰富的教程, 如Creating Your Own Java A ...
- FREERTOS 手册阅读笔记
郑重声明,版权所有! 转载需说明. FREERTOS堆栈大小的单位是word,不是byte. 根据处理器架构优化系统的任务优先级不能超过32,If the architecture optimized ...
- JS魔法堂:不完全国际化&本地化手册 之 理論篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- 转职成为TypeScript程序员的参考手册
写在前面 作者并没有任何可以作为背书的履历来证明自己写作这份手册的分量. 其内容大都来自于TypeScript官方资料或者搜索引擎获得,期间掺杂少量作者的私见,并会标明. 大部分内容来自于http:/ ...
- Redis学习手册(目录)
为什么自己当初要选择Redis作为数据存储解决方案中的一员呢?现在能想到的原因主要有三.其一,Redis不仅性能高效,而且完全免费.其二,是基于C/C++开发的服务器,这里应该有一定的感情因素吧.最后 ...
- JS魔法堂:不完全国际化&本地化手册 之 实战篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
随机推荐
- Kubernetes之总体了解
Kubernetes:架构.基本概念.用于总体了解 Kubernetes系列之介绍篇:优势.用途 Kubernetes核心概念总结
- 用Qemu模拟vexpress-a9 --- 配置 qemu 的网络功能
转载:http://wiki.sylixos.com/index.php/Linux%E7%8E%AF%E5%A2%83%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97 环境介 ...
- Python多线程爬虫
前言 用上多线程,感觉爬虫跑起来带着风 运行情况 爬取了9万多条文本记录,耗时比较短,一会儿就是几千条 关键点 多个线程对同一全局变量进行修改要加锁 # 获取锁,用于线程同步 threadLock.a ...
- jQuery 知识点总结
jQuery 是一个“写的更少,但做的更多”的轻量级JavaScript 库.对于网页开发者来说,学会jQuery是必要的.因为它让你了解业界最通用的技术,为将来学习更高级的库打下基础,并且确实可以很 ...
- MVC ---- 怎删改查
using Modelsop; using System; using System.Collections.Generic; using System.Linq; using System.Web; ...
- Python3简单爬虫抓取网页图片
现在网上有很多python2写的爬虫抓取网页图片的实例,但不适用新手(新手都使用python3环境,不兼容python2), 所以我用Python3的语法写了一个简单抓取网页图片的实例,希望能够帮助到 ...
- 【Python】【IO】
# [[IO]] # [文件读写] '''读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的.读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现 ...
- WebPack基本概念以及基本使用
入门Webpack,看这篇就够了 2017年9月18日更新,添加了一个使用webpack配置多页应用的demo,可以点击此处查看 2017年8月13日更新,本文依据webpack3.5.3将文章涉及代 ...
- 性能跃升50%!解密自主研发的金融级分布式关系数据库OceanBase 2.0
小蚂蚁说: 相信大家对蚂蚁金服自主研发的金融级分布式关系数据库OceanBase的故事不再陌生了.在刚刚过去的2018年天猫双11中,成交额2135亿再次创造了新纪录,而支撑今年双11的支付宝核心链路 ...
- 使用ajax无法跨源问题总结
参考文章: 浏览器同源政策及其规避方法 跨域资源共享 CORS 详解 使用jQuery实现跨域提交表单数据 <form action="http://v.juhe.cn/weather ...