您的位置:首页 > 其它

xstream简介(bean与xml转换工具)

2015-08-25 19:47 417 查看
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项目

只需要添加:

Java代码


<dependency>

<groupId>com.thoughtworks.xstream</groupId>

<artifactId>xstream</artifactId>

<version>1.4.3</version>

</dependency>

使用实例:

例子一:

定义类

Java代码


public class Person {

private String firstname;

private String lastname;

private PhoneNumber phone;

private PhoneNumber fax;

// ... constructors and methods

}

public class PhoneNumber {

private int code;

private String number;

// ... constructors and methods

}

初始化解析对象

Java代码


XStream xstream = new XStream();

如果不想使用xpp作为xml解析引擎,也可写为new XStream(new Dom4jDriver());

设置映射规则:

Java代码


xstream.alias("person", Person.class);

xstream.alias("phonenumber", PhoneNumber.class);

将对象序列化为xml

Java代码


Person joe = new Person("Joe", "Walnes");

joe.setPhone(new PhoneNumber(123, "1234-456"));

joe.setFax(new PhoneNumber(123, "9999-999"));

String xml = xstream.toXML(joe);

结果:

Java代码


<person>

<firstname>Joe</firstname>

<lastname>Walnes</lastname>

<phone>

<code>123</code>

<number>1234-456</number>

</phone>

<fax>

<code>123</code>

<number>9999-999</number>

</fax>

</person>

由xml生成对象

Java代码


Person newJoe = (Person)xstream.fromXML(xml);

当然xstream也支持注解,一下代码中使用到了 XstreamUtils 这个是在xstream基础上的封装,解决了现在xstream在日常使用中会出现的一些问题

Java代码


@XStreamAlias("TestBeanRoot")

class TestBean

{

private String testEl1;

@XStreamAlias("test_Rename_El2")

private String testEl2;

@XStreamAsAttribute

private String testAttr;

@XStreamOmitField

private String testSkip;

@XStreamImplicit(itemFieldName = "itemName", keyFieldName = "keyName")

private List<String> testList;

...getAndSet

}

XStream testBeanXstream = XstreamUtils.getXstream(XstreamUtilsTest.TestBean.class);

XstreamUtilsTest.TestBean tt = createTestBean();

System.out.println(testBeanXstream.toXML(tt));

"<TestBeanRoot testAttr=\"attr\">"

"<testEl1>el1</testEl1>"

+ "<test_Rename_El2>el2</test_Rename_El2>"

+ "<itemName>listItem1</itemName>"

+ "<itemName>listItem2</itemName>"

+ "</TestBeanRoot>"

如果存在多级el的情况,可以通过引用其他类的形式 如 private TestBean2 testBean2;,新的类内部又可以具有其他结构

xstream常用的注解有:

Java代码


@XStreamAlias

@XStreamAsAttribute

@XStreamOmitField

@XStreamImplicit

但看到很多文章,有这样的说法

1、xstream有bug,在转换过程中,会将 定义别名中的下划线“_”转换为xml后会变成“__”

2、在xml生成对象时,xml有多出来的元素时,对象生成将会抛出异常。

事实上从xstream源代码分析,这两个都不是问题,xstream都提供了对应的处理方式

具体参看工具类

Java代码


/**

* xstream工具封装

* 用以处理xml与bean的转换

*

* @author PengQingyang

* @version [版本号, 2012-10-5]

* @see [相关类/方法]

* @since [产品/模块版本]

*/

public class XstreamUtils

{

private static Logger logger = LoggerFactory.getLogger(XstreamUtils.class);

private static Map<Class<?>, XStream> xstreamMap = new WeakHashMap<Class<?>, XStream>();

/**

* 转换过程中特殊字符转码

*/

private static NameCoder nameCoder = new NameCoder()

{

public String encodeNode(String arg0)

{

return arg0;

}

public String encodeAttribute(String arg0)

{

return arg0;

}

public String decodeNode(String arg0)

{

return arg0;

}

public String decodeAttribute(String arg0)

{

return arg0;

}

};

/**

* 在xml中多余的节点生成bean时会抛出异常

* 通过该mapperWrapper跳过不存在的属性

* @param mapper

* @return [参数说明]

*

* @return MapperWrapper [返回类型说明]

* @exception throws [异常类型] [异常说明]

* @see [类、类#方法、类#成员]

*/

private static MapperWrapper createSkipOverElementMapperWrapper(

Mapper mapper)

{

MapperWrapper resMapper = new MapperWrapper(mapper)

{

/**

* @param elementName

* @return

*/

@SuppressWarnings("rawtypes")

@Override

public Class realClass(String elementName)

{

Class res = null;

;

try

{

res = super.realClass(elementName);

}

catch (CannotResolveClassException e)

{

logger.warn("xstream change xml to object. filed (0) not exsit. ",

elementName);

}

return res;

}

};

return resMapper;

}

/**

* 获取xstream转换对象

* @param classType

* @return [参数说明]

*

* @return XStream [返回类型说明]

* @exception throws [异常类型] [异常说明]

* @see [类、类#方法、类#成员]

*/

public static XStream getXstream(Class<?> classType)

{

return getXstream(classType, true);

}

/**

* 获取xstream转换对象

* @param classType

* @param isSkipOverElement

* @return [参数说明]

*

* @return XStream [返回类型说明]

* @exception throws [异常类型] [异常说明]

* @see [类、类#方法、类#成员]

*/

public static XStream getXstream(Class<?> classType,

boolean isSkipOverElement)

{

if (xstreamMap.containsKey(classType))

{

return xstreamMap.get(classType);

}

XStream res = null;

if (isSkipOverElement)

{

res = new XStream(new Xpp3DomDriver(nameCoder))

{

/**

* @param next

* @return

*/

protected MapperWrapper wrapMapper(MapperWrapper next)

{

return createSkipOverElementMapperWrapper(next);

}

};

}

else

{

res = new XStream(new Xpp3DomDriver(nameCoder));

}

logger.info("create xstream by {0} , parameter {1}", new Object[] {

classType.getName(), isSkipOverElement });

res.processAnnotations(classType);

xstreamMap.put(classType, res);

return res;

}

}

封装后的使用:

Java代码


private static xxxxXstream = XstreamUtils.getXstream(Xxxx.class);

method(){

xxxxXstream.toXML

xxxxXstream.fromXML

}

2012-10-22追加

如果想生成的xml是否换行,自己进行控制,可这样写

Java代码


/**

*<获取xstream转换对象>

*<功能详细描述>

* @param classType

* @param isSkipOverElement

* @param isNewLine

* @return [参数说明]

*

* @return XStream [返回类型说明]

* @exception throws [异常类型] [异常说明]

* @see [类、类#方法、类#成员]

*/

public static XStream getXstream(Class<?> classType,

boolean isSkipOverElement, boolean isNewLine) {

if (xstreamMap.containsKey(classType)) {

return xstreamMap.get(classType);

}

/**

* 生成domDriver 重写createWriter方法,使生成的domDriver在新的节点不会信生成一行

*/

HierarchicalStreamDriver domDriver = null;

if (isNewLine) {

domDriver = new Xpp3DomDriver(nameCoder);

} else {

domDriver = new Xpp3DomDriver(nameCoder) {

public HierarchicalStreamWriter createWriter(Writer out) {

return new PrettyPrintWriter(out, getNameCoder()) {

protected String getNewLine() {

return "";

}

};

}

};

}

XStream res = null;

if (isSkipOverElement) {

res = new XStream(domDriver) {

protected MapperWrapper wrapMapper(MapperWrapper next) {

return createSkipOverElementMapperWrapper(next);

}

};

} else {

res = new XStream(domDriver);

}

logger.info("create xstream by {0} , parameter {1}", new Object[] {

classType.getName(), isSkipOverElement });

res.processAnnotations(classType);

xstreamMap.put(classType, res);

return res;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: