java操作xml的传统的方式是用JAXP(Java Api for XML Processing),而从jdk5开始,又有了一种更强大的与xml互操作的方式,那就是JAXB(Java Api for XML Binding).JDK5需要单独下载JAXB的jar包,而JDK6当中就自带了JAXB。
要使用jaxb,需要对java对象贴上注解Annotation,常用的有这么三个:
@XmlRootElement:对应xml的根节点
@XmlElement:对应xml的一个元素节点
@XmlAtrribute:对应一个属性节点
下面我们就来看一个例子:
Gender.java
package xml.jaxb.demo2;
enum Gender{//这是一个普通的java 枚举类
MALE(true),
FEMALE (false);
private boolean value;
Gender(boolean _value){
value = _value;
}
}
Address.java
package xml.jaxb.demo2;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
class Address {
@XmlAttribute//说明country是作为address节点的属性
String country;
@XmlElement//说明city是作为address节点的子节点
String city;
String zipcode; //由于没有添加@XmlElement,所以该元素不会出现在输出的xml中
public Address() {
}
public Address(String country, String city, String zipcode) {
this.country = country;
this.city = city;
this.zipcode = zipcode;
}
public String toString(){
return country+","+city+","+zipcode;
}
}
Person.java:
package xml.jaxb.demo2;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement//表示person是一个根元素
class Person {
@XmlAttribute
String name; //name将作为person的的一个属性
@XmlElement
Date birthDay; //birthday将作为person的子元素
@XmlElement
Address address; //address将作为person的子元素
@XmlElement
Gender gender; //gender将作为person的子元素
public Person(){
}
public Person(Date birthDay, String name, Address address, Gender gender) {
this.birthDay = birthDay;
this.name = name;
this.address = address;
this.gender = gender;
}
public String toString(){
return new SimpleDateFormat("yyyy-MM-dd").format(birthDay)+","+name+","+address+","+gender;
}
}
下面我们下一个测试的代码:
package xml.jaxb.demo2;
import java.util.Date;
import org.w3c.dom.Document;
import static xml.jaxb.demo2.JAXBUtils.*;
//參考:http://emmagee.javaeye.com/blog/92505
public class JAXBTester {
//对象转变为byte数组
public static <T> byte[] dtoToByteArray(T dto) throws JAXBException{
/*客户端应用程序必须提供新上下文对象需要识别的类的列表。 新的上下文不仅要识别所有指定的类,还要识别直接/间接从指定类中静态引用的所有类。所引用类的子类或 @XmlTransient 引用类都不用在 JAXBContext 中注册。*/
JAXBContext context = JAXBContext.newInstance(dto.getClass());
Marshaller m = context.createMarshaller();
ByteArrayOutputStream out = new ByteArrayOutputStream();
m.marshal(dto, out);
return out.toByteArray();
}
public static void main(String[] args) throws Exception {
Date birthday = new Date();
String name = "xjs";
Address addr = new Address("china","dalian","0411");
Gender male = Gender.MALE;
Person p = new Person(birthday,name,addr,male);
byte[] arr = dtoToByteArray(p);
String str = new String(arr);
System.out.println(str);
}
}
输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><person name="xjs"><birthDay>2010-09-22T13:07:46.479+08:00</birthDay><address country="china"><city>dalian</city></address><gender>MALE</gender></person>
可以很清楚地看出来,person对象被转化成了一个xml的字符串。
在web服务里面,客户端与服务器是通过传递xml格式的SOAP消息来进行通信,现在就可以把对象转化成xml,在客户端与服务器之间进行传递。这就不要求对象必须实现Serializable接口。
这和对象序列化有本质的区别,序列化是把对象转化成二进制的字节数组,而JAXB是把对象转化成xml字符串。
下面我们再来写几个方法,帮助我们理解和使用JAXB。
package xml.jaxb.demo2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
/**
* @author xjs E-mail:xjs250@163.com
* @version 创建时间:2010-9-22 下午10:20:41
*/
public class JAXBUtils {
public static <T> void dtoToXml(T dto,String xml)throws JAXBException,IOException{
//对象转变为xml
JAXBContext context = JAXBContext.newInstance(dto.getClass());
Marshaller m = context.createMarshaller();
OutputStream out = new FileOutputStream(xml);
m.marshal(dto,out);
out.close();
}
@SuppressWarnings("unchecked")
public static <T> T xmlToDto(String xml,Class<T> clazz)throws JAXBException,IOException{
//xml转换为对象
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller um = context.createUnmarshaller();
InputStream in = new FileInputStream(xml);
T t = (T)um.unmarshal(in);
in.close();
return t;
}
@SuppressWarnings("unchecked")
public static <T> T xmlStringToDto(String xmlStr,Class<T> clazz) throws JAXBException{
//xml String 转化为对象
JAXBContext jc = JAXBContext.newInstance(clazz);
Unmarshaller u = jc.createUnmarshaller();
T ret = (T)u.unmarshal( new StreamSource( new StringReader( xmlStr ) ) );
return ret;
}
public static <T> String dtoToXmlString(T dto) throws JAXBException{
//xml String 转化为对象
JAXBContext jc = JAXBContext.newInstance(dto.getClass());
Marshaller m = jc.createMarshaller();
m.setProperty("jaxb.formatted.output", true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
Result result = new StreamResult(out);
m.marshal(dto, result);
return new String(out.toByteArray());
}
public static <T> byte[] dtoToByteArray(T dto) throws JAXBException{
//对象转变为byte数组
JAXBContext context = JAXBContext.newInstance(dto.getClass());
Marshaller m = context.createMarshaller();
ByteArrayOutputStream out = new ByteArrayOutputStream();
m.marshal(dto, out);
return out.toByteArray();
}
@SuppressWarnings("unchecked")
public static <T> T byteArrayToDto(byte[] arr,Class<T> clazz) throws JAXBException{
//byte数组转变为对象
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller um = context.createUnmarshaller();
ByteArrayInputStream in = new ByteArrayInputStream(arr);
T ret = (T)um.unmarshal(in);
return ret;
}
@SuppressWarnings("unchecked")
public static <T> T domToDto(Document dom,Class<T> clazz)throws JAXBException{
//dom转化成dto
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller um = context.createUnmarshaller();
T ret = (T)um.unmarshal(dom);
return ret;
}
public static <T> Document dtoToDom(T dto) throws JAXBException, ParserConfigurationException{
//dto转化成dom
JAXBContext context = JAXBContext.newInstance(dto.getClass());
Marshaller m = context.createMarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
m.marshal( dto, doc );
return doc;
}
public static <T> String domToString(Document dom,Class<T> clazz) throws JAXBException{
//dom转化成xml string
T dto = domToDto(dom,clazz);
return dtoToXmlString(dto);
}
public static <T> Document stringToDom(String xmlStr,Class<T> clazz) throws JAXBException, ParserConfigurationException{
//xml string转化成dom
T dto = xmlStringToDto(xmlStr,clazz);
return dtoToDom(dto);
}
}