jaxb 元素详解 @XmlRootElement @XmlType

XmlRootElement JAXB注解

[XmlRootElement JAXB注解]
Java代码
@Retention(value=RUNTIME)
@Target(value=TYPE)
public @interface XmlRootElement
@Inherited
@Retention(value=RUNTIME)
@Target(value={PACKAGE,TYPE})
public @interface XmlAccessorType

XmlRootElement:
标识这个类或枚举类型是根元素,将会被映射到 XML 元素中。
JAXB中的注解,用来根据java类生成xml内容。 当使用 @XmlRootElement 注释对顶层类或枚举类型进行注释时,类型值被表示为 XML 文档中的 XML 元素。 JAXB Annotation @XmlRootElement // xml 文件的根元素

@XmlElement
将java对象的属性映射为xml的节点。将没有get方法/set方法的属性映射到XML

@XmlAttribute
將ava对象的属性映射为xml的节点的属性。
  eleCode  

@XmlType(propOrder = { “id”, “name”, “age”,“book”})
指定属性输出顺序。

@XmlElementWrapper(name = “allnames”)
仅允许出现在集合属性上,在原xml结点上再包装一层xml节点。

@XmlAccessorOrder用于对java对象生成的xml元素进行排序。它有两个属性值:
AccessorOrder.ALPHABETICAL:对生成的xml元素按字母书序排序
XmlAccessOrder.UNDEFINED:不排序

@XmlJavaTypeAdaptor:参考Using JAXB 2.0’s XmlJavaTypeAdapter
标识一个接口类型的属性,返回Address接口的一个具体实现类的对象。

@XmlTransient(非瞬态)
用于标示在由Java对象映射XML时,忽略此属性,在生成的XML文件中将不出现此元素。

@XmlAccessorType // 控制默认情况下是否对字段或 Javabean 属性进行系列化。
**默认规则:
** 默认情况下,如果包中不存在 @XmlAccessorType,那么假定使用以下包级别注释。
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
默认情况下,如果类中不存在 @XmlAccessorType注解,并且没有任何超类是使用 @XmlAccessorType 注释的,则假定在类中使用以下默认注释: @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
可能值:
FIELD: 绑定类中的(每个,没有get方法/set方法的属性也可以)非静态、非瞬态字段将会自动绑定映射到 XML,除非由 XmlTransient 注释。
NONE: 所有字段或属性都不能绑定到 XML,除非使用一些 JAXB 注释专门对它们进行注释。
PROPERTY: 绑定类中的(每个,只有有get方法/set方法的属性才可以)自动绑定映射到 XML,除非由 XmlTransient 注释。
PUBLIC_MEMBER:每个公共获取方法/设置方法对和每个公共字段将会自动绑定到 XML,除非由 XmlTransient 注释。

XmlElement和@XmlAttribute区别描述
@XmlElement将java对象的属性映射为xml的节点。
@XmlAttribute將ava对象的属性映射为xml的节点的属性。

package jaxb;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAccessType;
@XmlRootElement // 必须要标明这个元素
@XmlAccessorType(XmlAccessType.FIELD)
public class Boy {
String name = “CY”;
}

package jaxb;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class JAXBTest {
public static void main(String[] args) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Boy.class);

    Marshaller marshaller = context.createMarshaller();  
    Unmarshaller unmarshaller = context.createUnmarshaller();  
     
    Boy boy = new Boy();  
    marshaller.marshal(boy, System.out);  
    System.out.println();  
     
    String xml = "David";  
    Boy boy2 = (Boy) unmarshaller.unmarshal(new StringReader(xml));  
    System.out.println(boy2.name);  
}  }  

执行结果:
 

CY

David (先 是marshall成 xml文件,再是把 xml 文件 unmarshal 成 java object。)

改动一: 
修改@XmlAccessorType(XmlAccessType.FIELD) --> @XmlAccessorType(XmlAccessType.PROPERTY) 意思是只有 属性 才能被转换成 xml 中的标签。

所以再运行的结果是:  CY 就是说 java object 转换成 xml 的时候,name 不是属性(因为没有 get set方法),所以name不转换成标签。

改动二: 
在 改动一 的基础上,给name属性添加 get set 方法。
再运行,结果为:

CY

David 由 此 可见 @XmlAccessorType 这个annotation 的作用。

改动三: 
在改动二 的基础上,给Boy 再添加一个field, int age=10, 即:
package jaxb;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAccessType;
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Boy {
String name = “CY”;
int age = 10;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} }
显然,这个age 是不会被 转化 到xml 文件中的。
解决办法是:
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAccessType;
@XmlRootElement // bixude
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Boy {

String name = "CY";  
@XmlElement  
int age = 10;  
public String getName() {  
    return name;  
}  

public void setName(String name) {  
    this.name = name;  
}  

}
加上 @XmlElement annotation. 运行结果为:

10 CY David 对于根元素,可以设置属性: @XmlRootElement(name="b" nameSpace="http://test") 这样,在生成的xml文件中, 标签 就会变为 标签。并且加上一个命名空间。 下面解释 @XmlJavaTypeAdaptor 的作用: @XmlRootElement @XmlAccessorType(XmlAccessType.PROPERTY) public class Boy {
private String name = "CY";  

private Address address; // 是一个接口  
 
public String getName() {  
    return name;  
}  

public void setName(String name) {  
    this.name = name;  
}  

}

在 java object 转换成 xml 的时候,接口Address 无法被转换。
所以 这里要加上 @XmlJavaTypeAdapter(AddressAdapter.class)
所以 要多写一个AddressAdaptor 类。这个类会返回Address接口的一个具体实现类的对象。
这 就是 @XmlJavaTypeAdapter 的作用

@XmlType注解标注xml生成顺序
默认情况下,Jaxb编组出来的xml中的字段顺序是随机的,你可以使用@XmlType的propOrder属性
来指定序列化的顺序。
 
第一步:定义java类时,使用@XmlType(propOrder = { “id”, “name”, “age”,“book”})指定属性输出顺序。
 
Java代码  
package step2;  
import java.util.Set;  
  
import javax.xml.bind.annotation.XmlElement;  
import javax.xml.bind.annotation.XmlElementWrapper;  
import javax.xml.bind.annotation.XmlRootElement;  
import javax.xml.bind.annotation.XmlType;  
  
@XmlRootElement  
@XmlType(propOrder = { “id”, “name”, “age”,“book”})  
public class Customer {  
    String name;  
    int age;  
    int id;  
    Set book;  
    @XmlElement(name=“name”)  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    @XmlElement(name=“age”)  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
    @XmlElement(name=“id”)  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
      
    @Override  
    public String toString() {  
        return “Customer [id=” + id + “,name=” + name + “,age=” + age + “,book=” + book + “]”;  
    }  
    @XmlElementWrapper(name=“books”)  
    @XmlElement(name=“book”)  
    public Set getBook() {  
        return book;  
    }  
  
    public void setBook(Set book) {  
        this.book = book;  
    }  
  
      
}  
 
输出的xml:
 
Xml代码

          100       suo       29                                 1               哈里波特               100.0                                     2               苹果               50.0                            注: 1.对于@XmlElementWrapper标注的属性,不能出现在@XmlType的propOrder列表中。 2.对于所有@XmlElement标注过的属性,必须出现在@XmlType的propOrder列表中。

@XmlElementWrapper注解表示生成一个包装器元素。该注释支持两种形式的序列化。

注意: @XmlElementWrapper仅允许出现在集合属性上。

第一步:定义将要转化的Java对象
    注

package jijian.test;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {
String[] names;
int age;
int id;

//使用@XmlElementWrapper注解后,将会在原xml结点上再包装一层xml节点
@XmlElementWrapper(name = "allnames")
@XmlElement(name = "myname")
public String[] getNames() {
	return names;
}
public void setNames(String[] names) {
	this.names = names;
}

@XmlElement
public int getAge() {
	return age;	
}
public void setAge(int age) {
	this.age = age;
}
@XmlAttribute
public int getId() {
	return id;
}
public void setId(int id) {
	this.id = id;
}

@Override
public String toString() {
	return "Customer [id = " + id + ",names = " + names + ",age = " + age + "]";
}

}

第二步: 生成xml文件并写入文件

package jijian.test;

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class Object2XmlDemo {

public static void main(String[] args) throws JAXBException {
	Customer customer = new Customer();
	customer.setId(100);
	customer.setNames(new String[]{"name-a","name-b","name-c"});
	customer.setAge(25);
	File file = new File("D:\\file.xml");
	JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);

	Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

	jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);	

	jaxbMarshaller.marshal(customer , file);

	jaxbMarshaller.marshal(customer, System.out);


}

}

生成的xml:

25 name-a name-b name-c

这个示范代码生成的xml同时写入了文件和标准输出(控制台):

XmlElement和@XmlAttribute区别描述
@XmlElement将java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。eg:@XmlElement该属性作为xml的element,且可以增加属性(name=“NewElementName”),那么生成的xml串的elment的标签是NewElementName
@XmlAttribute將被序列化为xml节点中的属性
证明    
 使用@XmlElement,并且带有name属性,修改生成的xml标签

package test.bean;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name=“rootclass”)

public class RootClass {

private EleClassA a;

private EleClassB b;

private String root;

private String rootA;

@XmlElement(name=“eleClassA”)

public EleClassA getA() {

return a;

}

public void setA(EleClassA a) {

this.a = a;

}

@XmlElement(name=“EleclassA”)

public EleClassB getB() {

return b;

}

public void setB(EleClassB b) {

this.b = b;

}

public String getRoot() {

return root;

}

public void setRoot(String root) {

this.root = root;

}

public String getRootA() {

return rootA;

}

public void setRootA(String rootA) {

this.rootA = rootA;

}

}

使用@XmlElement,并且不带有name属性

package test.bean;

import javax.xml.bind.annotation.XmlAttribute;

import javax.xml.bind.annotation.XmlElement;

public class EleClassA {

private String eleA;

private String eleB;

private String attrC;

@XmlElement

public String getEleA() {

return eleA;

}

public void setEleA(String eleA) {

this.eleA = eleA;

}

@XmlElement(name=“elebnewname”)

public String getEleB() {

return eleB;

}

public void setEleB(String eleB) {

this.eleB = eleB;

}

@XmlAttribute

public String getAttrC() {

return attrC;

}

public void setAttrC(String attrC) {

this.attrC = attrC;

}

}

使用@XmlAttribute

package test.bean;

import javax.xml.bind.annotation.XmlAttribute;

import javax.xml.bind.annotation.XmlElement;

public class EleClassB {

private String attrUserName;

private String attrPassword;

private String eleCode;

@XmlAttribute

public String getAttrUserName() {

return attrUserName;

}

public void setAttrUserName(String attrUserName) {

this.attrUserName = attrUserName;

}

@XmlAttribute(name=“password”)

public String getAttrPassword() {

return attrPassword;

}

public void setAttrPassword(String attrPassword) {

this.attrPassword = attrPassword;

}

@XmlElement

public String getEleCode() {

return eleCode;

}

public void setEleCode(String eleCode) {

this.eleCode = eleCode;

}

运行Test1类中main方法,执行结果:

package test;

import java.io.StringWriter;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.JAXBException;

import javax.xml.bind.Marshaller;

import test.bean.EleClassA;

import test.bean.EleClassB;

import test.bean.RootClass;

public class Test1 {

public static void main(String[] args) {

RootClass rc = new RootClass();

EleClassA a = new EleClassA();

EleClassB b = new EleClassB();

a.setAttrC(“attrc”);

a.setEleA(“eleA”);

a.setEleB(“eleB”);

b.setAttrPassword(“attrPassword”);

b.setAttrUserName(“attrUsrName”);

b.setEleCode(“eleCode”);

rc.setA(a);

rc.setB(b);

rc.setRoot(“root”);

rc.setRootA(“rootA”);

JAXBContext context;

try {

context = JAXBContext.newInstance(RootClass.class);

Marshaller mar = context.createMarshaller();

mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

mar.setProperty(Marshaller.JAXB_ENCODING, “UTF-8”);

StringWriter writer = new StringWriter();

mar.marshal(rc, writer);

System.out.println(writer.toString());

} catch (JAXBException e) {

e.printStackTrace();

}

}

}

     

eleA

eleB

eleCode

root

rootA

  

总结:
可以看出EleClassA这个类中,attrc上使用标签@XmlAttribute,在xml中北设置为eleClassA元素的属性。
在RootClass类中,geta上使用注解@XmlElement(name=“eleClassA”),在xml中变成了标签,其他的类似,可以看着类上的代码对比结果,来理解两者之间的区别。

你可能感兴趣的:(Java,工具类,java)