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项目
只需要添加:
使用实例:
例子一:
定义类
初始化解析对象
如果不想使用xpp作为xml解析引擎,也可写为new XStream(new Dom4jDriver());
设置映射规则:
将对象序列化为xml
结果:
由xml生成对象
当然xstream也支持注解,一下代码中使用到了 XstreamUtils 这个是在xstream基础上的封装,解决了现在xstream在日常使用中会出现的一些问题
如果存在多级el的情况,可以通过引用其他类的形式 如 private TestBean2 testBean2;,新的类内部又可以具有其他结构
xstream常用的注解有:
但看到很多文章,有这样的说法
1、xstream有bug,在转换过程中,会将 定义别名中的下划线“_”转换为xml后会变成“__”
2、在xml生成对象时,xml有多出来的元素时,对象生成将会抛出异常。
事实上从xstream源代码分析,这两个都不是问题,xstream都提供了对应的处理方式
具体参看工具类
封装后的使用:
2012-10-22追加
如果想生成的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>
使用实例:
例子一:
定义类
- 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
- }
初始化解析对象
- XStream xstream = new XStream();
如果不想使用xpp作为xml解析引擎,也可写为new XStream(new Dom4jDriver());
设置映射规则:
- xstream.alias("person", Person.class);
- xstream.alias("phonenumber", PhoneNumber.class);
将对象序列化为xml
- 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);
结果:
- <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生成对象
- Person newJoe = (Person)xstream.fromXML(xml);
当然xstream也支持注解,一下代码中使用到了 XstreamUtils 这个是在xstream基础上的封装,解决了现在xstream在日常使用中会出现的一些问题
- @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常用的注解有:
- @XStreamAlias
- @XStreamAsAttribute
- @XStreamOmitField
- @XStreamImplicit
但看到很多文章,有这样的说法
1、xstream有bug,在转换过程中,会将 定义别名中的下划线“_”转换为xml后会变成“__”
2、在xml生成对象时,xml有多出来的元素时,对象生成将会抛出异常。
事实上从xstream源代码分析,这两个都不是问题,xstream都提供了对应的处理方式
具体参看工具类
- /**
- * 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;
- }
- }
封装后的使用:
- private static xxxxXstream = XstreamUtils.getXstream(Xxxx.class);
- method(){
- xxxxXstream.toXML
- xxxxXstream.fromXML
- }
2012-10-22追加
如果想生成的xml是否换行,自己进行控制,可这样写
- /**
- *<获取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;
- }