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

来源:互联网 发布:手机淘宝投诉电话多少 编辑:程序博客网 时间:2024/05/23 10:54
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代码  收藏代码
  1. <dependency>  
  2.     <groupId>com.thoughtworks.xstream</groupId>  
  3.     <artifactId>xstream</artifactId>  
  4.     <version>1.4.3</version>  
  5. </dependency>  


    使用实例: 
    例子一: 
定义类 
Java代码  收藏代码
  1. public class Person {  
  2.   private String firstname;  
  3.   private String lastname;  
  4.   private PhoneNumber phone;  
  5.   private PhoneNumber fax;  
  6.   // ... constructors and methods  
  7. }  
  8. public class PhoneNumber {  
  9.   private int code;  
  10.   private String number;  
  11.   // ... constructors and methods  
  12. }  


初始化解析对象 
Java代码  收藏代码
  1. XStream xstream = new XStream();  

如果不想使用xpp作为xml解析引擎,也可写为new XStream(new Dom4jDriver()); 
设置映射规则: 
Java代码  收藏代码
  1. xstream.alias("person", Person.class);  
  2. xstream.alias("phonenumber", PhoneNumber.class);  


将对象序列化为xml 
Java代码  收藏代码
  1. Person joe = new Person("Joe""Walnes");  
  2. joe.setPhone(new PhoneNumber(123"1234-456"));  
  3. joe.setFax(new PhoneNumber(123"9999-999"));  
  4.   
  5. String xml = xstream.toXML(joe);  

结果: 
Java代码  收藏代码
  1. <person>  
  2.   <firstname>Joe</firstname>  
  3.   <lastname>Walnes</lastname>  
  4.   <phone>  
  5.     <code>123</code>  
  6.     <number>1234-456</number>  
  7.   </phone>  
  8.   <fax>  
  9.     <code>123</code>  
  10.     <number>9999-999</number>  
  11.   </fax>  
  12. </person>  


由xml生成对象 
Java代码  收藏代码
  1. Person newJoe = (Person)xstream.fromXML(xml);  


当然xstream也支持注解,一下代码中使用到了 XstreamUtils 这个是在xstream基础上的封装,解决了现在xstream在日常使用中会出现的一些问题 
Java代码  收藏代码
  1.   @XStreamAlias("TestBeanRoot")  
  2.   class TestBean  
  3.   {  
  4.       private String testEl1;  
  5.       @XStreamAlias("test_Rename_El2")  
  6.       private String testEl2;  
  7.       @XStreamAsAttribute  
  8.       private String testAttr;  
  9.       @XStreamOmitField  
  10.       private String testSkip;  
  11.       @XStreamImplicit(itemFieldName = "itemName", keyFieldName = "keyName")  
  12.       private List<String> testList;  
  13.       ...getAndSet  
  14.   }  
  15.   XStream testBeanXstream = XstreamUtils.getXstream(XstreamUtilsTest.TestBean.class);  
  16.   XstreamUtilsTest.TestBean tt = createTestBean();   
  17.   System.out.println(testBeanXstream.toXML(tt));  
  18.   
  19.   "<TestBeanRoot testAttr=\"attr\">"  
  20.   "<testEl1>el1</testEl1>"  
  21. "<test_Rename_El2>el2</test_Rename_El2>"  
  22. "<itemName>listItem1</itemName>"  
  23. "<itemName>listItem2</itemName>"   
  24. "</TestBeanRoot>"   

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

   xstream常用的注解有: 
Java代码  收藏代码
  1. @XStreamAlias  
  2.  @XStreamAsAttribute  
  3.  @XStreamOmitField  
  4.  @XStreamImplicit  


   但看到很多文章,有这样的说法 
   1、xstream有bug,在转换过程中,会将 定义别名中的下划线“_”转换为xml后会变成“__” 
   2、在xml生成对象时,xml有多出来的元素时,对象生成将会抛出异常。 

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

   具体参看工具类 

Java代码  收藏代码
  1. /** 
  2.   * xstream工具封装 
  3.   * 用以处理xml与bean的转换 
  4.   *  
  5.   * @author  PengQingyang 
  6.   * @version  [版本号, 2012-10-5] 
  7.   * @see  [相关类/方法] 
  8.   * @since  [产品/模块版本] 
  9.  */  
  10. public class XstreamUtils  
  11. {  
  12.     private static Logger logger = LoggerFactory.getLogger(XstreamUtils.class);  
  13.       
  14.     private static Map<Class<?>, XStream> xstreamMap = new WeakHashMap<Class<?>, XStream>();  
  15.       
  16.     /** 
  17.      * 转换过程中特殊字符转码 
  18.      */  
  19.     private static NameCoder nameCoder = new NameCoder()  
  20.     {  
  21.         public String encodeNode(String arg0)  
  22.         {  
  23.             return arg0;  
  24.         }  
  25.           
  26.         public String encodeAttribute(String arg0)  
  27.         {  
  28.             return arg0;  
  29.         }  
  30.           
  31.         public String decodeNode(String arg0)  
  32.         {  
  33.             return arg0;  
  34.         }  
  35.           
  36.         public String decodeAttribute(String arg0)  
  37.         {  
  38.             return arg0;  
  39.         }  
  40.     };  
  41.       
  42.     /** 
  43.       * 在xml中多余的节点生成bean时会抛出异常 
  44.       * 通过该mapperWrapper跳过不存在的属性 
  45.       * @param mapper 
  46.       * @return [参数说明] 
  47.       *  
  48.       * @return MapperWrapper [返回类型说明] 
  49.       * @exception throws [异常类型] [异常说明] 
  50.       * @see [类、类#方法、类#成员] 
  51.      */  
  52.     private static MapperWrapper createSkipOverElementMapperWrapper(  
  53.             Mapper mapper)  
  54.     {  
  55.         MapperWrapper resMapper = new MapperWrapper(mapper)  
  56.         {  
  57.             /** 
  58.              * @param elementName 
  59.              * @return 
  60.              */  
  61.             @SuppressWarnings("rawtypes")  
  62.             @Override  
  63.             public Class realClass(String elementName)  
  64.             {  
  65.                 Class res = null;  
  66.                 ;  
  67.                 try  
  68.                 {  
  69.                     res = super.realClass(elementName);  
  70.                 }  
  71.                 catch (CannotResolveClassException e)  
  72.                 {  
  73.                     logger.warn("xstream change xml to object. filed (0) not exsit. ",  
  74.                             elementName);  
  75.                 }  
  76.                 return res;  
  77.             }  
  78.         };  
  79.           
  80.         return resMapper;  
  81.     }  
  82.       
  83.     /** 
  84.      * 获取xstream转换对象 
  85.      * @param classType 
  86.      * @return [参数说明] 
  87.      *  
  88.      * @return XStream [返回类型说明] 
  89.      * @exception throws [异常类型] [异常说明] 
  90.      * @see [类、类#方法、类#成员] 
  91.     */  
  92.     public static XStream getXstream(Class<?> classType)  
  93.     {  
  94.         return getXstream(classType, true);  
  95.     }  
  96.       
  97.     /** 
  98.       * 获取xstream转换对象 
  99.       * @param classType 
  100.       * @param isSkipOverElement 
  101.       * @return [参数说明] 
  102.       *  
  103.       * @return XStream [返回类型说明] 
  104.       * @exception throws [异常类型] [异常说明] 
  105.       * @see [类、类#方法、类#成员] 
  106.      */  
  107.     public static XStream getXstream(Class<?> classType,  
  108.             boolean isSkipOverElement)  
  109.     {  
  110.         if (xstreamMap.containsKey(classType))  
  111.         {  
  112.             return xstreamMap.get(classType);  
  113.         }  
  114.           
  115.         XStream res = null;  
  116.         if (isSkipOverElement)  
  117.         {  
  118.             res = new XStream(new Xpp3DomDriver(nameCoder))  
  119.             {  
  120.                   
  121.                 /** 
  122.                  * @param next 
  123.                  * @return 
  124.                  */  
  125.                 protected MapperWrapper wrapMapper(MapperWrapper next)  
  126.                 {  
  127.                     return createSkipOverElementMapperWrapper(next);  
  128.                 }  
  129.                   
  130.             };  
  131.         }  
  132.         else  
  133.         {  
  134.             res = new XStream(new Xpp3DomDriver(nameCoder));  
  135.         }  
  136.           
  137.         logger.info("create xstream by {0} , parameter {1}"new Object[] {  
  138.                 classType.getName(), isSkipOverElement });  
  139.           
  140.         res.processAnnotations(classType);  
  141.           
  142.         xstreamMap.put(classType, res);  
  143.           
  144.         return res;  
  145.     }  
  146.       
  147. }  


     封装后的使用: 
Java代码  收藏代码
  1. private static xxxxXstream = XstreamUtils.getXstream(Xxxx.class);  
  2.   
  3. method(){  
  4.    xxxxXstream.toXML  
  5.    xxxxXstream.fromXML  
  6. }  



2012-10-22追加 
如果想生成的xml是否换行,自己进行控制,可这样写 


Java代码  收藏代码
  1. /** 
  2.       *<获取xstream转换对象> 
  3.       *<功能详细描述> 
  4.       * @param classType 
  5.       * @param isSkipOverElement 
  6.       * @param isNewLine 
  7.       * @return [参数说明] 
  8.       *  
  9.       * @return XStream [返回类型说明] 
  10.       * @exception throws [异常类型] [异常说明] 
  11.       * @see [类、类#方法、类#成员] 
  12.      */  
  13.     public static XStream getXstream(Class<?> classType,  
  14.             boolean isSkipOverElement, boolean isNewLine) {  
  15.         if (xstreamMap.containsKey(classType)) {  
  16.             return xstreamMap.get(classType);  
  17.         }  
  18.           
  19.         /** 
  20.          * 生成domDriver 重写createWriter方法,使生成的domDriver在新的节点不会信生成一行 
  21.          */  
  22.         HierarchicalStreamDriver domDriver = null;  
  23.         if (isNewLine) {  
  24.             domDriver = new Xpp3DomDriver(nameCoder);  
  25.         } else {  
  26.             domDriver = new Xpp3DomDriver(nameCoder) {  
  27.                 public HierarchicalStreamWriter createWriter(Writer out) {  
  28.                     return new PrettyPrintWriter(out, getNameCoder()) {  
  29.                         protected String getNewLine() {  
  30.                             return "";  
  31.                         }  
  32.                     };  
  33.                 }  
  34.             };  
  35.         }  
  36.           
  37.         XStream res = null;  
  38.         if (isSkipOverElement) {  
  39.             res = new XStream(domDriver) {  
  40.                 protected MapperWrapper wrapMapper(MapperWrapper next) {  
  41.                     return createSkipOverElementMapperWrapper(next);  
  42.                 }  
  43.             };  
  44.         } else {  
  45.             res = new XStream(domDriver);  
  46.         }  
  47.           
  48.         logger.info("create xstream by {0} , parameter {1}"new Object[] {  
  49.                 classType.getName(), isSkipOverElement });  
  50.           
  51.         res.processAnnotations(classType);  
  52.           
  53.         xstreamMap.put(classType, res);  
  54.           
  55.         return res;  
  56.     }  
0 0
原创粉丝点击