在學習jsp的時候我們都會學習到XStream,但是一般情況下我們是不需要經常使用XStream的,但是仍會有小伙伴們會好奇XStream的使用方法,那么今天錯新小編就為大家詳細介紹。
XStream中的核心類就是XStream類,一般來說,熟悉這個類基本就夠用了,如果你用的更多,估計是你設計有問題,否則不需要。
XStream對象相當Java對象和XML之間的轉換器,轉換過程是雙向的。創建XSteam對象的方式很簡單,只需要new?XStream()即可。
Java到xml,用toXML()方法。
Xml到Java,用fromXML()方法。
在沒有任何設置默認情況下,java到xml的映射,是java成員名對應xml的元素名,java類的全名對應xml根元素的名字。而實際中,往往是xml和java類都有了,要完成相互轉換,必須進行別名映射。
別名配置包含三種情況:
1、類別名,用alias(String?name,?Class?type)。
2、類成員別名,用aliasField(String?alias,?Class?definedIn,?String?fieldName)
3、類成員作為屬性別名,用?aliasAttribute(Class?definedIn,?String?attributeName,?String?alias),單獨命名沒有意義,還要通過useAttributeFor(Class?definedIn,?String?fieldName)?應用到某個類上。
別名的配置是非常重要的,但是其中有些細節問題很重要,在例子中會專門做詳細說明。
另外還有不太常用的方法:
addImplicitCollection(Class?ownerType,?String?fieldName),去掉集合類型生成xml的父節點。
registerConverter(Converter?converter)?,注冊一個轉換器。
如果你的xml很大,或者為了安全性,以流的方式傳輸,那么XStream也提供豐富的API,
使用起來也非常簡便。目前還用不到,暫不考慮。
如果這些基本的操作還不能滿足你應用的需求,XStream提供豐富的擴展點。你可以實現自己的轉換器。還可以利用XStream完成更負責的功能,比如輸出其他非xml格式的數據,還可以輸出html,還支持XML?Dom類型數據,這些應用起來稍微復雜些。當然這些不是XStream應用的重點,也不用理會,真正需要的時候再查看API和源碼研究研究。
XStream的優點很多,但是也有一些小bug,比如在定義別名中的下劃線“_”轉換為xml后會變成“__”這個符號,很變態。因此,盡量避免在別名中實用任何符號,卻是需要下劃線的時候,可以考慮實用連接符“-”,這個沒有問題。
另外,我們的Java?Bean中,常常有一些常量,在轉換過程,XStream也會將這些常量轉換過去,形成常量的xml節點,這顯然不是想要的結果,對于常量字段,就不做轉換了。
?
下面給出一個非常典型的而且實用的例子,作為對總結的補充:
package?test;?
import?java.util.List;?
/**?
*?Created?by?IntelliJ?IDEA.<br>?
*?<b>User</b>:?leizhimin<br>?
*?<b>Date</b>:?2008-5-22?21:10:13<br>?
*?<b>Note</b>:?Please?add?comment?here!?
*/?
public?class?Person?{?
????private?String?name;?
????private?String?age;?
????private?Profile?profile;?
????private?List<Address>?addlist;?
????public?Person(String?name,?String?age,?Profile?profile,?List<Address>?addlist)?{?
????????this.name?=?name;?
????????this.age?=?age;?
????????this.profile?=?profile;?
????????this.addlist?=?addlist;?
????}?
????public?String?toString()?{?
????????return?"Person{"?+?
????????????????"name='"?+?name?+?'/''?+?
????????????????",?age='"?+?age?+?'/''?+?
????????????????",?profile="?+?profile?+?
????????????????",?addlist="?+?addlist?+?
????????????????'}';?
????}?
}
package?test;?
import?java.sql.Date;?
/**?
*?Created?by?IntelliJ?IDEA.<br>?
*?<b>User</b>:?leizhimin<br>?
*?<b>Date</b>:?2008-5-22?21:10:32<br>?
*?<b>Note</b>:?Please?add?comment?here!?
*/?
public?class?Profile?{?
????private?String?job;?
????private?String?tel;?
????private?String?remark;?
????public?Profile(String?job,?String?tel,?String?remark)?{?
????????this.job?=?job;?
????????this.tel?=?tel;?
????????this.remark?=?remark;?
????}?
????public?String?toString()?{?
????????return?"Profile{"?+?
????????????????"job='"?+?job?+?'/''?+?
????????????????",?tel='"?+?tel?+?'/''?+?
????????????????",?remark='"?+?remark?+?'/''?+?
????????????????'}';?
????}?
}
package?test;?
/**?
*?Created?by?IntelliJ?IDEA.<br>?
*?<b>User</b>:?leizhimin<br>?
*?<b>Date</b>:?2008-5-22?21:10:22<br>?
*?<b>Note</b>:?Please?add?comment?here!?
*/?
public?class?Address?{?
????private?String?add;?
????private?String?zipcode;?
????public?Address(String?add,?String?zipcode)?{?
????????this.add?=?add;?
????????this.zipcode?=?zipcode;?
????}?
????public?String?toString()?{?
????????return?"Address{"?+?
????????????????"add='"?+?add?+?'/''?+?
????????????????",?zipcode='"?+?zipcode?+?'/''?+?
????????????????'}';?
????}?
}
package?test;?
import?com.thoughtworks.xstream.XStream;?
import?java.util.List;?
import?java.util.ArrayList;?
/**?
*?Created?by?IntelliJ?IDEA.<br>?
*?<b>User</b>:?leizhimin<br>?
*?<b>Date</b>:?2008-5-22?21:10:47<br>?
*?<b>Note</b>:?XStream學習[http://lavasoft.blog.51cto.com]?
*/?
public?class?TestXStream?{?
????public?static?void?main(String?args[])?{?
????????test();?
????}?
????public?static?void?test()?{?
????????System.out.println("----------XStream學習:http://lavasoft.blog.51cto.com----------");?
????????//目標對象?
????????Address?address1?=?new?Address("鄭州市經三路",?"450001");?
????????Address?address2?=?new?Address("西安市雁塔路",?"710002");?
????????List<Address>?addList?=?new?ArrayList<Address>();?
????????addList.add(address1);?
????????addList.add(address2);?
????????Profile?profile?=?new?Profile("軟件工程師",?"13512129933",?"備注說明");?
????????Person?person?=?new?Person("熔巖",?"27",?profile,?addList);?
????????//轉換裝配?
????????XStream?xStream?=?new?XStream();?
????????/**************????設置類別名???****************/?
????????xStream.alias("PERSON",?test.Person.class);?
????????xStream.alias("PROFILE",?test.Profile.class);?
????????xStream.alias("ADDRESS",?test.Address.class);?
????????output(1,?xStream,?person);?
????????/*************??設置類成員的別名?***************/?
????????//設置Person類的name成員別名Name?
????????xStream.aliasField("Name",?Person.class,?"name");?
????????/*[注意]?設置Person類的profile成員別名PROFILE,這個別名和Profile類的別名一致,?
?????????*?這樣可以保持XStream對象可以從profile成員生成的xml片段直接轉換為Profile成員,?
?????????*?如果成員profile的別名和Profile的別名不一致,則profile成員生成的xml片段不可?
?????????*?直接轉換為Profile對象,需要重新創建XStream對象,這豈不給自己找麻煩????????*/?
????????xStream.aliasField("PROFILE",?test.Person.class,?"profile");?
????????xStream.aliasField("ADDLIST",?test.Person.class,?"addlist");?
????????xStream.aliasField("Add",?test.Address.class,?"add");?
????????xStream.aliasField("Job",?test.Profile.class,?"job");?
????????output(2,?xStream,?person);?
????????/*******??設置類成員為xml一個元素上的屬性?*******/?
????????xStream.useAttributeFor(Address.class,?"zipcode");?
????????/*************??設置屬性的別名?***************/?
????????xStream.aliasAttribute(test.Address.class,?"zipcode",?"Zipcode");?
????????output(3,?xStream,?person);?
????????/*************??將xml轉為java對象?******×****/?
????????String?person_xml?=?"<PERSON>/n"?+?
????????????????"??<Name>熔巖</Name>/n"?+?
????????????????"??<age>27</age>/n"?+?
????????????????"??<PROFILE>/n"?+?
????????????????"????<Job>軟件工程師</Job>/n"?+?
????????????????"????<tel>13512129933</tel>/n"?+?
????????????????"????<remark>備注說明</remark>/n"?+?
????????????????"??</PROFILE>/n"?+?
????????????????"??<ADDLIST>/n"?+?
????????????????"????<ADDRESS?Zipcode=/"450001/">/n"?+?
????????????????"??????<Add>鄭州市經三路</Add>/n"?+?
????????????????"????</ADDRESS>/n"?+?
????????????????"????<ADDRESS?Zipcode=/"710002/">/n"?+?
????????????????"??????<Add>西安市雁塔路</Add>/n"?+?
????????????????"????</ADDRESS>/n"?+?
????????????????"??</ADDLIST>/n"?+?
????????????????"</PERSON>";?
????????String?profile_xml?=?"??<PROFILE>/n"?+?
????????????????"????<Job>軟件工程師</Job>/n"?+?
????????????????"????<tel>13512129933</tel>/n"?+?
????????????????"????<remark>備注說明</remark>/n"?+?
????????????????"??</PROFILE>";?
????????String?address_xml?=?"????<ADDRESS?Zipcode=/"710002/">/n"?+?
????????????????"??????<Add>西安市雁塔路</Add>/n"?+?
????????????????"????</ADDRESS>";?
????????//同樣實用上面的XStream對象xStream?
????????System.out.println(xStream.fromXML(person_xml).toString());?
????????System.out.println(xStream.fromXML(profile_xml).toString());?
????????System.out.println(xStream.fromXML(address_xml).toString());?
????}?
????public?static?void?output(int?i,?XStream?xStream,?Object?obj)?{?
????????String?xml?=?xStream.toXML(obj);?
????????System.out.println(">>>第[?"?+?i?+?"]次輸出/n");?
????????System.out.println(xml?+?"/n");?
????}?
}
----------XStream學習:http://lavasoft.blog.51cto.com----------?
>>>第[?1]次輸出?
<PERSON>?
??<name>熔巖</name>?
??<age>27</age>?
??<profile>?
????<job>軟件工程師</job>?
????<tel>13512129933</tel>?
????<remark>備注說明</remark>?
??</profile>?
??<addlist>?
????<ADDRESS>?
??????<add>鄭州市經三路</add>?
??????<zipcode>450001</zipcode>?
????</ADDRESS>?
????<ADDRESS>?
??????<add>西安市雁塔路</add>?
??????<zipcode>710002</zipcode>?
????</ADDRESS>?
??</addlist>?
</PERSON>?
>>>第[?2]次輸出?
<PERSON>?
??<Name>熔巖</Name>?
??<age>27</age>?
??<PROFILE>?
????<Job>軟件工程師</Job>?
????<tel>13512129933</tel>?
????<remark>備注說明</remark>?
??</PROFILE>?
??<ADDLIST>?
????<ADDRESS>?
??????<Add>鄭州市經三路</Add>?
??????<zipcode>450001</zipcode>?
????</ADDRESS>?
????<ADDRESS>?
??????<Add>西安市雁塔路</Add>?
??????<zipcode>710002</zipcode>?
????</ADDRESS>?
??</ADDLIST>?
</PERSON>?
>>>第[?3]次輸出?
<PERSON>?
??<Name>熔巖</Name>?
??<age>27</age>?
??<PROFILE>?
????<Job>軟件工程師</Job>?
????<tel>13512129933</tel>?
????<remark>備注說明</remark>?
??</PROFILE>?
??<ADDLIST>?
????<ADDRESS?Zipcode="450001">?
??????<Add>鄭州市經三路</Add>?
????</ADDRESS>?
????<ADDRESS?Zipcode="710002">?
??????<Add>西安市雁塔路</Add>?
????</ADDRESS>?
??</ADDLIST>?
</PERSON>?
Person{name='熔巖',?age='27',?profile=Profile{job='軟件工程師',?tel='13512129933',?remark='備注說明'},?addlist=[Address{add='鄭州市經三路',?zipcode='450001'},?Address{add='西安市雁塔路',?zipcode='710002'}]}?
Profile{job='軟件工程師',?tel='13512129933',?remark='備注說明'}?
Address{add='西安市雁塔路',?zipcode='710002'}?
Process?finished?with?exit?code?0
在實際中,類的屬性很多,嵌套層次也很復雜,如果僅僅使用XStream原生API來硬編碼設置別名等屬性,顯得太生硬也難以維護。完全可以考慮通過一個xml配置文件來定義所有用到的類的別名定義(包括其成員),然后,通過讀取配置構建一個XStream的工廠,在用到時候直接去取,而不是讓實用者組裝。我目前的一個項目中,就是這么實現的,效果非常的好。
下面我給出針對上面提出的問題一個解決方案:
思想:考慮做一個過濾器,在xml轉java之前,在Java轉xml之后,應用這個過濾器。這個過濾器提供將xml中的“__”替換為“-”,并且將xml中的不需要的節點剔除。
在過濾之前,我實現了個轉換器裝配,這一步通過xml來配置,并在java中獲取。
代碼就省略了,這一步很靈活,關鍵看你的應用了。
為了能過濾xml,我們需要用Dom4j遞歸遍歷xml文檔。下面一些算法代碼:
????//遞歸算法:遍歷配置文件,找出所有有效的xpath?
????private?static?void?recursiveElement(Element?element)?{?
????????List<Element>?elements?=?element.elements();?
????????validXPathList.add(element.getPath());?
????????if?(elements.size()?==?0)?{?
????????????//沒有子元素?
????????}?else?{?
????????????//有子元素?
????????????for?(Iterator<Element>?it?=?elements.iterator();?it.hasNext();)?{?
????????????????//遞歸遍歷?
????????????????recursiveElement(it.next());?
????????????}?
????????}?
????}?
????//遞歸算法:遍歷xml,標識無效的元素節點?
????private?static?void?recursiveFixElement(Element?element)?{?
????????List<Element>?elements?=?element.elements();?
????????if?(!validXPathList.contains(element.getPath()))?{?
????????????element.addAttribute("delete",?"true");?
????????}?
????????if?(elements.size()?==?0)?{?
????????????//沒有子元素?
????????}?else?{?
????????????//有子元素?
????????????for?(Iterator<Element>?it?=?elements.iterator();?it.hasNext();)?{?
????????????????Element?e?=?it.next();?
????????????????if?(!validXPathList.contains(e.getPath()))?{?
????????????????????e.addAttribute("delete",?"true");?
????????????????}?
????????????????//遞歸遍歷?
????????????????recursiveFixElement(e);?
????????????}?
????????}?
????}?
????/**?
?????*?過濾器接口方法,轉換不規范字符,剔除無效節點?
?????*?
?????*?@param?xmlStr?要過濾的xml?
?????*?@return?符合轉換器要求的xml?
?????*/?
????public?static?String?filter(String?xmlStr)?{?
????????Document?document?=?null;?
????????try?{?
????????????document?=?DocumentHelper.parseText(xmlStr.replaceAll("__",?"_"));?
????????????//遞歸的調用:標記要剔除的xml元素?
????????????recursiveFixElement(document.getRootElement());??????
????????????List<Node>?nodeList?=?document.selectNodes("http://@delete");?
????????????for?(Node?node?:?nodeList)?{?
????????????????node.getParent().detach();??//剔除xml元素?
????????????}?
????????}?catch?(DocumentException?e)?{?
????????????System.out.println(e.getMessage());?
????????????e.printStackTrace();?
????????}?
????????return?document.asXML();?
????}
上述就是小編為大家介紹關于XStream的使用方法,看完后是不是大家都對XStream的使用方法有了一定的了解呢?
新聞熱點
疑難解答