JAXB

本文部分转自http://blog.csdn.net/czplplp_900725/article/details/7888896

在JDK1.6开始,SUN将JAXB放到了JDK中,配合JDK5的特性Annotation可以很方便的与jax-rs、jax-ws集成,极大的简化了web service接口的开发工作量。 

就因为如此,在webservice实现中为避免遇到这样那样的问题,对JAXB的API的熟悉是非常有必要的:

  1.@XmlRootElement

  用于类级别的注解,对应xml的根元素,常与 @XmlType 和 @XmlAccessorType一起使用。属性:name,用于为根元素节点取名。默认为类名。如:

@XmlRootElement(name = "REQUEST")  // 根节点为REQUEST,
生成的XML:<?xml version="1.0" encoding="UTF-8" standalone="yes"?><REQUEST id="1"><NAME>李四</NAME><AGE>20</AGE></REQUEST>
  2.@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的元素

  注意:

  a.@XmlAccessorType的默认访问级别是XmlAccessType.PUBLIC_MEMBER,因此,如果java对象中的private成员变量设置了public权限的getter/setter方法,就不要在private变量上使用@XmlElement和@XmlAttribute注解,否则在由java对象生成xml时会报同一个属性在java类里存在两次的错误。

  b.如果@XmlAccessorType的访问权限为XmlAccessType.NONE,如果在java的成员变量上使用了@XmlElement或@XmlAttribute注解,这些成员变量依然可以映射到xml文件。

  c.用了@XmlAccessorType(XmlAccessType.FIELD),所以没有使用注解@XmlElement,xml中依然会生成这些元素。

  3.@XmlAccessorOrder

  用于对java对象生成的xml元素进行排序。它有两个属性值:

  XmlAccessorOrder.ALPHABETICAL:对生成的xml元素按字母书序排序

  XmlAccessOrder.UNDEFINED:不排序

  4.@XmlType

  用在class类的注解,常与@XmlRootElement,@XmlAccessorType一起使用。它有三个属性:name、propOrder、namespace,经常使用的只有propOrder一个属性。

  注意:
  a.对于@XmlElementWrapper标注的属性,不能出现在@XmlType的propOrder列表中。
   b.对于所有@XmlElement标注过的属性,必须出现在@XmlType的propOrder列表中。

  5.@XmlAttribute

  用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。如:
    @XmlAttribute
    public int ID;

  6.@XmlElement

  将java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。如:

  @XmlElement(name = "REAL_NAME")
  public String NAME;
  7.@XmlTransient

  @XmlTransient用于标示在由java对象映射xml时,忽略此属性。即,在生成的xml文件中不出现此元素。

  8.@XmlJavaTypeAdapter

  @XmlJavaTypeAdapter常用在转换比较复杂的对象时,如map类型或者格式化日期等。使用此注解时,需要自己写一个adapter类继承XmlAdapter抽象类,并实现里面的方法。如:

  @XmlJavaTypeAdapter(value=xxx.class),value为自己定义的adapter类。

  9.@XmlElementWrapper  

  为数组元素或集合元素定义一个父节点。如,类中有一元素为List items,若不加此注解,该元素将被映射为

<WORKER id="1">
  <REAL_NAME>工人1</REAL_NAME>
  <AGE>0</AGE>
</WORKER>
<WORKER id="2">
  <REAL_NAME>工人2</REAL_NAME>
  <AGE>0</AGE>
</WORKER>

这种形式,此注解可将这个元素进行包装,如:

  @XmlElementWrapper(name="WORKERS")
  @XmlElement(name="WORKER")
  public List<Worker> WORKER;

将会生成这样的XML样式:

<WORKERS>
   <WORKER id="1">
      <REAL_NAME>工人1</REAL_NAME>
      <AGE>0</AGE>
   </WORKER>
   <WORKER id="2">
      <REAL_NAME>工人2</REAL_NAME>
        <AGE>0</AGE>
    </WORKER>
</WORKERS>

  10.@XmlSeeAlso

指示JAXB,包装此类的同时,包装子类。也就是让子类继承父类的xml包装逻辑。该注解写在父类里。如:

@XmlSeeAlso({ Employee.class,Boss.class })

用例代码如下:

  • java类

实体类 - 基类:Person.java

 1 package model;
 2 import java.util.Date;
 3 import javax.xml.bind.annotation.XmlAccessType;
 4 import javax.xml.bind.annotation.XmlAccessorType;
 5 import javax.xml.bind.annotation.XmlAttribute;
 6 import javax.xml.bind.annotation.XmlElement;
 7 import javax.xml.bind.annotation.XmlSeeAlso;
 8 import javax.xml.bind.annotation.XmlTransient;
 9 import javax.xml.bind.annotation.XmlType;
10 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
11 import adapter.DateTimeAdapter;
12  
13 @XmlAccessorType(XmlAccessType.FIELD)
14 @XmlSeeAlso({Employee.class,Boss.class})
15 @XmlType(propOrder = {
16         "ID",
17         "NAME",
18         "AGE",
19         "BIRTH",
20         "EMAIL",
21         "ZIP",
22         "ADDRESS"
23 })
24 public class Person {
25     @XmlAttribute
26     public int ID;
27     @XmlElement(name = "REAL_NAME")
28     public String NAME;
29     @XmlElement
30     public int AGE;
31     @XmlElement
32     @XmlJavaTypeAdapter(value = DateTimeAdapter.class)
33     public Date BIRTH;
34     @XmlTransient
35     public String JOB;
36     public String EMAIL;
37     public String ZIP;
38     public String ADDRESS;
39     
41     public int getID() {
42         return ID;
43     }
44     public void setID(int iD) {
45         ID = iD;
46     }
47     public String getNAME() {
48         return NAME;
49     }
50     public void setNAME(String nAME) {
51         NAME = nAME;
52     }
53     public int getAGE() {
54         return AGE;
55     }
56     public void setAGE(int aGE) {
57         AGE = aGE;
58     }
59     public Date getBIRTH() {
60         return BIRTH;
61     }
62     public void setBIRTH(Date bIRTH) {
63         BIRTH = bIRTH;
64     }
65     public String getEMAIL() {
66         return EMAIL;
67     }
68     public void setEMAIL(String eMAIL) {
69         EMAIL = eMAIL;
70     }
71     public String getZIP() {
72         return ZIP;
73     }
74     public void setZIP(String zIP) {
75         ZIP = zIP;
76     }
77     public String getADDRESS() {
78         return ADDRESS;
79     }
80     public void setADDRESS(String aDDRESS) {
81         ADDRESS = aDDRESS;
82     }
83     public String getJOB() {
84         return JOB;
85     }
86     public void setJOB(String jOB) {
87         JOB = jOB;
88     }
89 }

子类:Boss.java

 1 package model;
 2 import java.util.List;
 3 import javax.xml.bind.annotation.XmlElement;
 4 import javax.xml.bind.annotation.XmlElementWrapper;
 5 import javax.xml.bind.annotation.XmlRootElement;
 6  
 7 @XmlRootElement(name = "REQUEST")
 8 public class Boss extends Person{
 9     @XmlElementWrapper(name="WORKERS")  
10     @XmlElement(name="WORKER")  
11     public List<Worker> WORKER;
12     
13     public List<Worker> getWORKER() {
14         return WORKER;
15     }
16     public void setWORKER(List<Worker> wORKER) {
17         WORKER = wORKER;
18     }    
19 }

子类:Worker.java

package model;

public class Worker extends Person{

}

适配器类:DateTimeAdapter.java

 1 package adapter;
 2 import java.text.SimpleDateFormat;
 3 import java.util.Date;
 4 import javax.xml.bind.annotation.adapters.XmlAdapter;
 5 
 6 public class DateTimeAdapter extends XmlAdapter<String, Date> {
 7 
 8     private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 9 
10     @Override
11     public String marshal(Date v) throws Exception {
12         return dateFormat.format(v);
13     }
14 
15     @Override
16     public Date unmarshal(String v) throws Exception {
17         return dateFormat.parse(v);
18     }
19 }

main:JaxbTest1.java

 1 package jaxb;
 2 import java.io.StringReader;
 3 import java.io.StringWriter;
 4 import java.io.Writer;
 5 import java.text.ParseException;
 6 import java.text.SimpleDateFormat;
 7 import java.util.ArrayList;
 8 import java.util.List;
 9 import javax.xml.bind.JAXBContext;
10 import javax.xml.bind.JAXBElement;
11 import javax.xml.bind.JAXBException;
12 import javax.xml.bind.Marshaller;
13 import javax.xml.bind.Unmarshaller;
14 import javax.xml.transform.stream.StreamSource;
15 import model.Boss;
16 import model.Worker;
17 
18 public class JaxbTest1 {
19     public static void main(String[] args) throws JAXBException, ParseException {
20         
21         Boss boss = new Boss();
22         boss.setID(1);
23         boss.setNAME("李四");
24         boss.setAGE(20);
25         
26         boss.setEMAIL("abc@163.com");
27         boss.setZIP("000000");
28         boss.setADDRESS("中华人民共和国");
29         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
30         boss.setBIRTH(dateFormat.parse("1990-09-09 09:09:09"));
31         boss.setJOB("教师");
32 
33         Worker worker1 = new Worker();
34         worker1.setID(1);
35         worker1.setNAME("工人1");
36 
37         Worker worker2 = new Worker();
38         worker2.setID(2);
39         worker2.setNAME("工人2");
40         
41         List<Worker> workers = new ArrayList<Worker>();
42         workers.add(worker1);
43         workers.add(worker2);
44         boss.setWORKER(workers); 
45         
46         JAXBContext context = JAXBContext.newInstance(Boss.class);
47         Marshaller marsheller = context.createMarshaller();
48         Unmarshaller unmarsheller = context.createUnmarshaller();
49         
50         // marshal
51         System.err.println("marshal:");
52         Writer writer = new StringWriter();
53         marsheller.marshal(boss, writer);
54         String xml = writer.toString();
55         System.out.println(xml);
56         System.out.println();
57         
58         // unmarshal
59         // String xml = "<REQUEST><REAL_NAME>zhangsan</REAL_NAME></REQUEST>";
60         JAXBElement<Boss> root = unmarsheller.unmarshal(new StreamSource(new StringReader(xml)),Boss.class);
61         Boss boss2 = root.getValue();
62         System.err.println("unmarshal:");
63         System.out.println(boss2.getNAME());
64     }
65 }

输出:

 1 marshal:
 2 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 3 <REQUEST id="1">
 4   <REAL_NAME>李四</REAL_NAME>
 5   <AGE>20</AGE>
 6   <BIRTH>1990-09-09 09:09:09</BIRTH>
 7   <EMAIL>abc@163.com</EMAIL>
 8   <ZIP>000000</ZIP>
 9   <ADDRESS>中华人民共和国</ADDRESS>
10   <WORKERS>
11     <WORKER id="1">
12       <REAL_NAME>工人1</REAL_NAME>
13       <AGE>0</AGE>
14     </WORKER>
15     <WORKER id="2">
16       <REAL_NAME>工人2</REAL_NAME>
17       <AGE>0</AGE>
18     </WORKER>
19   </WORKERS>
20 </REQUEST>
21 
22 unmarshal:
23 李四

有纰漏之处,欢迎大家的指正建议。

环境:JDK1.6,MAVEN,eclipse

源码地址:http://files.cnblogs.com/files/xiluhua/JAXB.rar

JDK地址:http://pan.baidu.com/s/1i3L6hal

原文地址:https://www.cnblogs.com/xiluhua/p/4472695.html