Jaxb2 技术指南.docx
《Jaxb2 技术指南.docx》由会员分享,可在线阅读,更多相关《Jaxb2 技术指南.docx(16页珍藏版)》请在冰豆网上搜索。
Jaxb2技术指南
Jaxb2
——完成Java对象和XML相互转换
前面有介绍过json-lib这个框架,在线博文:
以及Jackson这个框架,在线博文:
它们都可以完成Java对象到XML的转换,但是还不是那么的完善。
还有XStream对JSON及XML的支持,它可以对JSON或XML的完美转换。
在线博文:
以及介绍Castor来完成Java对象到xml的相互转换。
在线博文:
这次介绍Jaxb2完成xml的转换,Jaxb2使用了JDK的新特性。
如:
Annotation、GenericType等,Jaxb2需要在即将转换的JavaBean中添加annotation注解。
下面我们就来看看Jaxb2是怎么样完成Java对象到XML之间的相互转换吧。
一、准备工作
1、资源准备
a)官方文档:
b)Jar包下载:
如果你有添加jdk的jar到工程中,在rt.jar中就带有jaxb2。
一般情况下不用自己添加jaxb2的jar。
2、程序前代码准备
packagecom.hoo.test;
importjava.io.IOException;
importjava.io.StringReader;
importjava.io.StringWriter;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjavax.xml.bind.JAXBContext;
importjavax.xml.bind.JAXBException;
importjavax.xml.bind.Marshaller;
importjavax.xml.bind.Unmarshaller;
importorg.junit.After;
importorg.junit.Before;
importorg.junit.Test;
importcom.hoo.entity.Account;
importcom.hoo.entity.AccountBean;
importcom.hoo.entity.Birthday;
importcom.hoo.entity.ListBean;
importcom.hoo.entity.MapBean;
/**
*function:
Jaxb2完成Java和XML的编组、解组
*@authorhoojo
*@createDate2011-4-25上午11:
54:
06
*@fileJaxb2Test.java
*@packagecom.hoo.test
*@projectWebHttpUtils
*@blog
*@emailhoojo_@
*@version1.0
*/
publicclassJaxb2Test{
privateJAXBContextcontext=null;
privateStringWriterwriter=null;
privateStringReaderreader=null;
privateAccountBeanbean=null;
@Before
publicvoidinit(){
bean=newAccountBean();
bean.setAddress("北京");
bean.setEmail("email");
bean.setId
(1);
bean.setName("jack");
Birthdayday=newBirthday();
day.setBirthday("2010-11-22");
bean.setBirthday(day);
try{
context=JAXBContext.newInstance(AccountBean.class);
}catch(Exceptione){
e.printStackTrace();
}
}
@After
publicvoiddestory(){
context=null;
bean=null;
try{
if(writer!
=null){
writer.flush();
writer.close();
}
if(reader!
=null){
reader.close();
}
}catch(IOExceptione){
e.printStackTrace();
}
System.gc();
}
publicvoidfail(Objecto){
System.out.println(o);
}
publicvoidfailRed(Objecto){
System.err.println(o);
}
}
通过JAXBContext的newInstance方法,传递一个class就可以获得一个上下文。
newInstance方法也可以传递一个xml的文件的path。
通过xml文件,对class的描述进行转换。
然后,就可以通过这个上下文的来创建一个Marshaller,通过Marshaller对象的marshal方法就可以转换JavaBean对象到xml。
同样JAXBContext也可以创建一个Unmarshall的unmarshal方法可以进行xml到Java对象的解组。
二、对Java编组、XML解组
1、JavaBean和XML的相互转换
代码如下:
@Test
publicvoidtestBean2XML(){
try{
//下面代码演示将对象转变为xml
Marshallermar=context.createMarshaller();
writer=newStringWriter();
mar.marshal(bean,writer);
fail(writer);
//下面代码演示将上面生成的xml转换为对象
reader=newStringReader(writer.toString());
Unmarshallerunmar=context.createUnmarshaller();
bean=(AccountBean)unmar.unmarshal(reader);
fail(bean);
}catch(JAXBExceptione){
e.printStackTrace();
}
}
上面的context是在init方法中创建的,它传递了一个AccountBean的class,这个AccountBean不是一般的普通的bean。
除了它带有getter、setter方法外,还有Annotation注解。
下面我们就看看这个bean的代码。
packagecom.hoo.entity;
importjavax.xml.bind.annotation.XmlAttribute;
importjavax.xml.bind.annotation.XmlRootElement;
importcom.sun.xml.internal.txw2.annotation.XmlElement;
@XmlRootElement(name="account")
publicclassAccountBean{
privateintid;
privateStringname;
privateStringemail;
privateStringaddress;
privateBirthdaybirthday;
@XmlElement
publicBirthdaygetBirthday(){
returnbirthday;
}
publicvoidsetBirthday(Birthdaybirthday){
this.birthday=birthday;
}
@XmlAttribute(name="number")
publicintgetId(){
returnid;
}
publicvoidsetId(intid){
this.id=id;
}
@XmlElement
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
@XmlElement
publicStringgetEmail(){
returnemail;
}
publicvoidsetEmail(Stringemail){
this.email=email;
}
@XmlElement
publicStringgetAddress(){
returnaddress;
}
publicvoidsetAddress(Stringaddress){
this.address=address;
}
@Override
publicStringtoString(){
returnthis.name+"#"+this.id+"#"+this.address+"#"+this.birthday+"#"+this.email;
}
}
上面的XmlRootElement是设置当前对象转换成xml后的根节点,name的值是设置根节点的名称。
在getter方法上设置XmlElement表示这个方法对应的属性是一个xml元素,如果这个注解还设置了name,那么这个name就是转换后xml的名称。
在一个属性上设置XmlAttribute,表示这个方法对应的属性在转换xml后是父元素的一个属性。
XmlAttribute的name就是转换后xml的属性的name。
运行后,结果如下:
xmlversion="1.0"encoding="UTF-8"standalone="yes"?
>北京2010-11-22emailjack
jack#1#北京#2010-11-22#email
把转换后的xml和上面的AccountBean对应看看
2、对List类型对象,进行编组、解组
@Test
publicvoidtestList2XML(){
ListBeanlistBean=newListBean();
listBean.setName("listtoxml");
List
list.add(bean);
bean=newAccountBean();
bean.setAddress("china");
bean.setEmail("tom@");
bean.setId
(2);
bean.setName("tom");
Birthdayday=newBirthday("2010-11-22");
bean.setBirthday(day);
Accountacc=newAccount();
acc.setAddress("china");
acc.setEmail("tom@");
acc.setId
(2);
acc.setName("tom");
day=newBirthday("2010-11-22");
acc.setBirthday(day);
list.add(bean);
list.add(acc);
listBean.setList(list);
try{
context=JAXBContext.newInstance(ListBean.class);
//下面代码演示将对象转变为xml
Marshallermar=context.createMarshaller();
writer=newStringWriter();
mar.marshal(listBean,writer);
fail(writer);
//下面代码演示将上面生成的xml转换为对象
reader=newStringReader(writer.toString());
Unmarshallerunmar=context.createUnmarshaller();
listBean=(ListBean)unmar.unmarshal(reader);
fail(listBean.getList().get(0));
fail(listBean.getList().get
(1));
fail(listBean.getList().get
(2));
}catch(JAXBExceptione){
e.printStackTrace();
}
}
你不能直接new一个List,然后将对象放到List中。
进行编组、解组,这样会出现异常情况的。
你需要构建一个JavaBean,在bean中创建一个List的属性。
然后在这个属性的getter方法上进行Annotation注解。
下面我们看看ListBean的代码:
packagecom.hoo.entity;
importjava.util.List;
importjavax.xml.bind.annotation.XmlAttribute;
importjavax.xml.bind.annotation.XmlElement;
importjavax.xml.bind.annotation.XmlElements;
importjavax.xml.bind.annotation.XmlRootElement;
@SuppressWarnings("unchecked")
@XmlRootElement(name="list-bean")
publicclassListBean{
privateStringname;
privateListlist;
@XmlElements({
@XmlElement(name="account",type=Account.class),
@XmlElement(name="bean",type=AccountBean.class)
})
publicListgetList(){
returnlist;
}
publicvoidsetList(Listlist){
this.list=list;
}
@XmlAttribute
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
}
XmlElements表示是一个集合类型,然后注解在集合中存放上面类型的对象。
XmlElement表示在集合中存放的一个对象类型和元素名称。
转换后结果如下:
xmlversion="1.0"encoding="UTF-8"standalone="yes"?
>北京2010-11-22emailjackchina2010-11-22tom@tomchina2010-11-22tom@2tom
jack#1#北京#2010-11-22#email
tom#2#china#2010-11-22#tom@
2#tom#tom@#china#2010-11-22
转换后的XML和Bean的注解的描述是一样的吧。
3、对Map集合进行解组、编组
/**
*function:
Map需要自己实现,可以构造一个简单的Map对象实现
*
*@authorhoojo
*@createDate2010-12-1上午10:
23:
26
*/
@Test
publicvoidtestMap2XML(){
MapBeanmapBean=newMapBean();
HashMapmap=newHashMap();
map.put("NO1",bean);
bean=newAccountBean();
bean.setAddress("china");
bean.setEmail("tom@");
bean.setId
(2);
bean.setName("tom");
Birthdayday=newBirthday("2010-11-22");
bean.setBirthday(day);
map.put("NO2",bean);
mapBean.setMap(map);
try{
context=JAXBContext.newInstance(MapBean.class);
//下面代码演示将对象转变为xml
Marshallermar=context.createMarshaller();
writer=newStringWriter();
mar.marshal(mapBean,writer);
fail(writer);
//下面代码演示将上面生成的xml转换为对象
reader=newStringReader(writer.toString());
Unmarshallerunmar=context.createUnmarshaller();
mapBean=(MapBean)unmar.unmarshal(reader);
fail(mapBean.getMap());
}catch(JAXBExceptione){
e.printStackTrace();
}
}
下面看看MapBean的代码
packagecom.hoo.entity;
importjava.util.HashMap;
importjavax.xml.bind.annotation.XmlRootElement;
importjavax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
importcom.hoo.util.MapAdapter;
@XmlRootElement
publicclassMapBean{
privateHashMapmap;
@XmlJavaTypeAdapter(MapAdapter.class)
publicHashMapgetMap(){
returnmap;
}
publicvoidsetMap(HashMapmap){
this.map=map;
}
}
上面的map集合的getter方法有一个XmlJavaTypeAdapter,需要传递一个Adapter的类型。
下面看看MyAdapter的代码
packagecom.hoo.util;
importjava.util.HashMap;
importjava.util.Map;
importjavax.xml.bind.annotation.adapters.XmlAdapter;
importcom.hoo.entity.AccountBean;
/**
*function:
AccountBean编组、解组的XmlAdapter
*@authorhoojo
*@createDate2011-4-25下午0