博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jaxb 完全手册
阅读量:7115 次
发布时间:2019-06-28

本文共 13690 字,大约阅读时间需要 45 分钟。

hot3.png

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随便.做验证用的.

org.hibernate.javax.persistence
hibernate-jpa-2.0-api
1.0.1.Final
org.hibernate
hibernate-validator
5.0.1.Final

1. JDK中JAXB相关的重要Class和Interface:

  • JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。
  • Marshaller接口,将Java对象序列化为XML数据。
  • Unmarshaller接口,将XML数据反序列化为Java对象。

 这个是简单的入门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);
 }

实际案例:

 

package jaxb.shop;import java.util.Date;import java.text.SimpleDateFormat;import javax.xml.bind.annotation.adapters.XmlAdapter;public class DateAdapter extends XmlAdapter
{ 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对象

 

在某个类中如下使用,解析出对应的时间格式.必须重载那2个方法,用于JAXB marshal xml,xml unmarshal object时候使用.

 

import javax.xml.bind.annotation.XmlSchemaType;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;@XmlElement(name = "TransactionTime", required = true) @XmlSchemaType(name = "dateTime") @XmlJavaTypeAdapter(DatetimeAdapter.class) protected Date transactionTime;

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示例.

110
Credo
China BeiJing
programmer
Accompany my girlfriend.
2009-06-02T12:00:00
2109-06-02T12:00:00
Write some code.
2009-06-02T12:00:00
2029-06-02T12:00:00

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
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
getOverinfos() { return overinfos; } public void setOverinfos(List
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
contextCache = new ConcurrentHashMap
(); 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
list = new ArrayList
(); 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的 结构

 

 

转载于:https://my.oschina.net/zhaoqian/blog/179334

你可能感兴趣的文章
HDU 5805
查看>>
不安装执行apk的方法(参考地址)
查看>>
rsyslog+mariadb+loganalyzer实现日志服务器搭建
查看>>
selenium+Firefox 初试
查看>>
单元测试利器 JUnit 4
查看>>
[TopCoder] SRM580, DIV1, 600p, Solution
查看>>
linux下修改IP信息
查看>>
编码风格
查看>>
第四章作业
查看>>
centos 6 切换base源
查看>>
[转]VC2005环境下boost_1_34_0编译手记
查看>>
【转】 Understanding Component-Entity-Systems
查看>>
post和get的区别
查看>>
20172313 2018-2019-1 《程序设计与数据结构》实验三报告
查看>>
list_test
查看>>
【Android-功能】Android应用增量更新
查看>>
测试工具。
查看>>
apache2.2与tomcat集成(可以多个tomcat)
查看>>
SCO连接AD / SCOM
查看>>
关于favicon.ico,shortcut icon,icon
查看>>