xstream简介(bean与xml转换工具)
本文
解决了"_"显示为"__"的问题。
解决了当xml的element属性多余bean的映射问题
解决了生成xml换行的问题
作用:
能够简单的通过
xstreamInstance.fromXML(xmlContent); 获取到对象
xstreamInstance.toXML(beanInstance); 将对象转换为xml
官网:
http://xstream.codehaus.org/
适用场景
bean与xml存在相互转换的场景:配置文件读取,报文解析,生成报文
从官方的版本演进上看,还提供了hibernate,json配置文件的读取。从1.4版本以后,新加入hibernate相关处理的逻辑,该部分功能尚未详细了解。
不适用场景
xml文件较大(比如有个10M的xml文件解析,就不太适用,因一次性解析,以及生成对象将会造成内存溢出)
效率
经过实测对象10个属性,对应xml。
xstream采用默认xml引擎,效率是dom4j解析的10倍左右(具体效率与代码实现有关,dom4j也能实现较高性能的解析)
总体来说,利用xstream能够大大提高,xml解析的入门,以及编写方便
具体事例:
如何应用:
从xstream的pom文件分析
只需要将xstream.jar xpp3.jar xmlpull.jar放入项目即可
如果为maven项目
只需要添加:
- <dependency>
- <groupId>com.thoughtworks.xstream</groupId>
- <artifactId>xstream</artifactId>
- <version>1.4.3</version>
- </dependency>
使用实例:
例子一:
定义类
publicclassPerson{
privateStringfirstname;
privateStringlastname;
privatePhoneNumberphone;
privatePhoneNumberfax;
}
classPhoneNumber{
privateintcode;
privateStringnumber;
}
初始化解析对象
XStreamxstream=newXStream();
如果不想使用xpp作为xml解析引擎,也可写为new XStream(new Dom4jDriver());
设置映射规则:
xstream.alias("person",Person.class);
xstream.alias("phonenumber",PhoneNumber.class);
将对象序列化为xml
Personjoe=newPerson("Joe","Walnes");
joe.setPhone(newPhoneNumber(123,"1234-456"));
joe.setFax("9999-999"));
Stringxml=xstream.toXML(joe);
结果:
<person>
<firstname>Joe</firstname>
<lastname>Walnes</lastname>
<phone>
<code>123</code>
<number>1234-456</number>
</phone>
<fax>
9999-999</number>
</fax>
</person>
由xml生成对象
PersonnewJoe=(Person)xstream.fromXML(xml);
当然xstream也支持注解,一下代码中使用到了 XstreamUtils 这个是在xstream基础上的封装,解决了现在xstream在日常使用中会出现的一些问题
@XStreamAlias("TestBeanRoot")
classTestBean
{
privateStringtestEl1;
@XStreamAlias("test_Rename_El2")
privateStringtestEl2;
@XStreamAsAttribute
privateStringtestAttr;
@XStreamOmitField
privateStringtestSkip;
@XStreamImplicit(itemFieldName="itemName",keyFieldName="keyName")
privateList<String>testList;
...getAndSet
XStreamtestBeanXstream=XstreamUtils.getXstream(XstreamUtilsTest.TestBean. XstreamUtilsTest.TestBeantt=createTestBean();
System.out.println(testBeanXstream.toXML(tt));
"<TestBeanRoottestAttr="attr">"
"<testEl1>el1</testEl1>"
+"<test_Rename_El2>el2</test_Rename_El2>"
+"<itemName>listItem1</itemName>"
+"<itemName>listItem2</itemName>"
+"</TestBeanRoot>"
如果存在多级el的情况,可以通过引用其他类的形式 如 private TestBean2 testBean2;,新的类内部又可以具有其他结构
xstream常用的注解有:
@XStreamAlias
@XStreamImplicit
但看到很多文章,有这样的说法
1、xstream有bug,在转换过程中,会将 定义别名中的下划线“_”转换为xml后会变成“__”
2、在xml生成对象时,xml有多出来的元素时,对象生成将会抛出异常。
事实上从xstream源代码分析,这两个都不是问题,xstream都提供了对应的处理方式
具体参看工具类
/**
*xstream工具封装
*用以处理xml与bean的转换
*
*@authorPengQingyang
*@version[版本号,2012-10-5]
*@see[相关类/方法]
*@since[产品/模块版本]
*/
classXstreamUtils
staticLoggerlogger=LoggerFactory.getLogger(XstreamUtils.staticMap<Class<?>,XStream>xstreamMap=newWeakHashMap<Class<?>,XStream>();
*转换过程中特殊字符转码
staticNameCodernameCoder=newNameCoder()
publicStringencodeNode(Stringarg0)
returnarg0;
publicStringencodeAttribute(Stringarg0)
publicStringdecodeNode(Stringarg0)
publicStringdecodeAttribute(Stringarg0)
};
*在xml中多余的节点生成bean时会抛出异常
*通过该mapperWrapper跳过不存在的属性
*@parammapper
*@return[参数说明]
*@returnMapperWrapper[返回类型说明]
*@exceptionthrows[异常类型][异常说明]
*@see[类、类#方法、类#成员]
staticMapperWrappercreateSkipOverElementMapperWrapper(
Mappermapper)
MapperWrapperresMapper=newMapperWrapper(mapper)
*@paramelementName
*@return
@SuppressWarnings("rawtypes")
@Override
publicClassrealClass(StringelementName)
Classres=null;
;
try
res=super.realClass(elementName);
catch(CannotResolveClassExceptione)
logger.warn("xstreamchangexmltoobject.filed(0)notexsit.",
elementName);
returnres;
returnresMapper;
*获取xstream转换对象
*@paramclassType
*@returnXStream[返回类型说明]
staticXStreamgetXstream(Class<?>classType)
returngetXstream(classType,true);
*@paramisSkipOverElement
staticXStreamgetXstream(Class<?>classType,85); font-weight:bold">booleanisSkipOverElement)
if(xstreamMap.containsKey(classType))
returnxstreamMap.get(classType);
XStreamres=if(isSkipOverElement)
newXStream(newXpp3DomDriver(nameCoder))
*@paramnext
protectedMapperWrapperwrapMapper(MapperWrappernext)
returncreateSkipOverElementMapperWrapper(next);
else
newXpp3DomDriver(nameCoder));
logger.info("createxstreamby{0},parameter{1}",85); font-weight:bold">newObject[]{
classType.getName(),isSkipOverElement});
res.processAnnotations(classType);
xstreamMap.put(classType,res);
封装后的使用:
staticxxxxXstream=XstreamUtils.getXstream(Xxxx. method(){
xxxxXstream.toXML
xxxxXstream.fromXML
2012-10-22追加
如果想生成的xml是否换行,自己进行控制,可这样写
*<获取xstream转换对象>
*<功能详细描述>
*@paramisNewLine
booleanisSkipOverElement,85); font-weight:bold">booleanisNewLine){
if(xstreamMap.containsKey(classType)){
*生成domDriver重写createWriter方法,使生成的domDriver在新的节点不会信生成一行
HierarchicalStreamDriverdomDriver=if(isNewLine){
domDriver=newXpp3DomDriver(nameCoder);
}else{
newXpp3DomDriver(nameCoder){
publicHierarchicalStreamWritercreateWriter(Writerout){
returnnewPrettyPrintWriter(out,getNameCoder()){
protectedStringgetNewLine(){
return"";
if(isSkipOverElement){
newXStream(domDriver){
protectedMapperWrapperwrapMapper(MapperWrappernext){
newXStream(domDriver);
}
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|