JAXB是什么?
JAXB(即Java Architecturefor XML Binding)是一个业界的标准,
即是一项可以根据XML Schema产生Java类的技术。
该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,
并能将Java对象树的内容重新写到XML实例文档。
两个个JAXB的实体类的例子:
//例子2
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="", propOrder={"log"})
@XmlRootElement(name="info")
public class LogReportMsg
{
@XmlElement(required=true)
protected List<Log> log;
@XmlAttribute
protected String id;
@XmlAttribute
protected String type;
public List<Log> getLog()
{
if (this.log == null) {
this.log = new ArrayList();
}
return this.log;
}
public String getId()
{
return this.id;
}
public void setId(String value)
{
this.id = value;
}
public String getType()
{
if (this.type == null) {
return "login_info";
}
return this.type;
}
public void setType(String value)
{
this.type = value;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="")
public static class Log
{
@XmlAttribute
protected String account;
@XmlAttribute
protected String accountType;
public String getAccount()
{
return this.account;
}
public void setAccount(String value)
{
this.account = value;
}
public String getAccountType()
{
if (this.accountType == null) {
return "2";
}
return this.accountType;
}
public void setAccountType(String value)
{
this.accountType = value;
}
}
}
//模版
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="info">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="log">
<xs:complexType>
<xs:attribute name="account" type="xs:string"/>
<xs:attribute name="accountType" type="xs:string" fixed="2"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string"/>
<xs:attribute name="type" type="xs:string" fixed="cdr_login_info"/>
</xs:complexType>
</xs:element>
</xs:schema>
//例子2
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="alarmType" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="alarmTime" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="alarmDesc" type="{http://www.w3.org/2001/XMLSchema}string"/>
* </sequence>
* <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" fixed="alarm_event" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"alarmType",
"alarmTime",
"alarmDesc"
})
@XmlRootElement(name = "info")
public class AlarmReqMsg {
@XmlElement(required = true)
protected String alarmType;
@XmlElement(required = true)
protected String alarmTime;
@XmlElement(required = true)
protected String alarmDesc;
@XmlAttribute(required = true)
protected String id;
@XmlAttribute(required = true)
protected String type;
//自动生成的 set/get 方法
}
//模版
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="info">
<xs:complexType>
<xs:sequence>
<xs:element name="alarmType" type="xs:string"/>
<xs:element name="alarmTime" type="xs:string"/>
<xs:element name="alarmDesc" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="required" fixed="alarm_event"/>
</xs:complexType>
</xs:element>
</xs:schema>
注解介绍
1) @XmlType
2) @XmlElement
3) @XmlRootElement
4) @XmlAttribute
5) @XmlAccessorType
6) @XmlAccessorOrder (不常用)
7) @XmlTransient (不常用)
8) @XmlJavaTypeAdapter (不常用)
1) @XmlType
@XmlType用在class类的注解,常与@XmlRootElement,@XmlAccessorType一起使用。
它有三个属性:name、propOrder、namespace,经常使用的只有前两个属性。如:
@XmlType(name = "basicStruct", propOrder = {
"intValue",
"stringArray",
"stringValue"
)
在使用@XmlType的propOrder 属性时,必须列出JavaBean对象中的所有属性,否则会报错。
在上面的例子中,不用列出也没事
2) @XmlElement
@XmlElement将java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。如:
@XmlElement(name="Address")
private String yourAddress;
3) @XmlRootElement
@XmlRootElement用于类级别的注解,对应xml的跟元素,常与 @XmlType 和 @XmlAccessorType一起使用。如:
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Address {}
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文件。
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);
}
2 使用举例
例子1:
package test;
public class Classroom {
private int id;
private String name;
private int grade;
public Classroom() {
super();
}
public Classroom(int id, String name, int grade) {
super();
this.id = id;
this.name = name;
this.grade = grade;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
}
package test;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Student {
private int id;
private String name;
private int age;
private Classroom classroom;
public Student() {
super();
}
public Student(int id, String name, int age, Classroom classroom) {
super();
this.id = id;
this.name = name;
this.age = age;
this.classroom = classroom;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Classroom getClassroom() {
return classroom;
}
public void setClassroom(Classroom classroom) {
this.classroom = classroom;
}
}
package test;
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 Test {
public static void beanToXML(){
Classroom classroom = new Classroom(1, "软件工程", 4);
Student student = new Student(101,"张三", 22, classroom);
try {
JAXBContext context = JAXBContext.newInstance(Student.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(student, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public static void XMLStringToBean(){
//
String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
"<student><age>22</age>" +
"<classroom><grade>4</grade><id>1</id><name>软件工程</name></classroom>" +
"<id>101</id><name>张三</name></student>";
try {
JAXBContext context = JAXBContext.newInstance(Student.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Student student = (Student)unmarshaller.unmarshal(new StringReader(xmlStr));
System.out.println(student.getAge());
System.out.println(student.getClassroom().getName());
} catch (JAXBException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
beanToXML();
// XMLStringToBean();
}
}
结果:
生成文件为
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
<age>22</age>
<classroom>
<grade>4</grade>
<id>1</id>
<name>软件工程</name>
</classroom>
<id>101</id>
<name>张三</name>
</student>
例子2
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MessageHelper {
final private Logger LOGGER = LoggerFactory.getLogger(getClass());
private Map<Class<? extends Object>, JAXBContext> contextMap = new HashMap<Class<? extends Object>, JAXBContext>();
private static MessageHelper instance;
private MessageHelper(){
InputStream in =getClass().getClassLoader().getResourceAsStream("msgClasses"); //将需要处理的类放在这里,带包名
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line ="";
while(true){
try {
line = reader.readLine();
} catch (IOException e) {
LOGGER.error("read msgClasses error",e);
}
if(line == null){
break;
}else{
String className = line.trim();
Class<? extends Object> clazz;
try {
clazz = Class.forName(className);
JAXBContext context = JAXBContext.newInstance(clazz);
contextMap.put(clazz, context);
} catch (ClassNotFoundException e) {
LOGGER.error("ClassNotFound",e);
} catch (JAXBException e) {
LOGGER.error("init jaxbContext error className is"+className,e);
}
}
}
}
public static MessageHelper getInstance(){
if(instance == null){
synchronized(MessageHelper.class){
if(instance == null){
instance = new MessageHelper();
}
}
}
return instance;
}
@SuppressWarnings("unchecked")
public <T>T unmarshal(String str,Class<T> clazz){
T result = null;
StringReader reader = new StringReader(str); //字符读
try {
Unmarshaller unmarshaller = contextMap.get(clazz).createUnmarshaller();
result = (T) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
LOGGER.error("unmarshal xml error",e);
}
return result;
}
public <T> String marshal(Object obj,Class<T> clazz) {
StringWriter writer = new StringWriter(); //字符串写
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
try {
Marshaller marshaller = contextMap.get(clazz).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(obj, writer);
} catch (JAXBException e) {
LOGGER.error("marshal xml error",e);
}
return writer.toString();
}
}
//调用
MessageHelper.getInstance().marshal(AA, AA.class)
MessageHelper.getInstance().unmarshal(sb.toString(), AA.class);