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随便.做验证用的.
?
1
2
3
4
5
6
7
8
9
10
<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);
 }

实际案例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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示例.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<? 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):
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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并发处理:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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的 结构
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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方法测试:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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的 结构

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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>
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值