• XStream 与 JAXB 的使用对比


    摘要

    前几天在开发一个功能的时候,需要用到Java bean 和 xml 格式字符串之间的互转工具。
    这边介绍两个工具,XStream 和 jdk 自带的 JAXB 系列工具类。

    XStream

    例如有如下的一个Java bean

    Student s1 = new Student();
    s1.setName("john");
    s1.setAge(21);
    
    • 1
    • 2
    • 3

    使用XStream进行转换时,你将得到如下的xml字符串

    <com.test.mytest.Student>
        <name>john</name>
        <age>21</age>
    </com.test.mytest.Student>
    
    • 1
    • 2
    • 3
    • 4

    也许你注意到了,XStream 在将java bean转化为xml格式的字符串时,根节点会默认转化为全路径。这显然不合理,我们生成xml格式字符串,作为报文传给对方系统,显然使用全路径是不合理的。然后XStream提供了别名功能,可以使用别名。这里有两种方式可以指定别名,一种是代码形式,一种是注解形式。推荐使用注解形式。

    1. 代码形式
    XStream xstream = new XStream();  
    // 将Student类使用类名作为别名
    xstream.alias(Student.class.getSimpleName(), Student.class); 
    Student student = new Student();  
    student.setName("pli");  
    student.setAge(18);  
    String xmlStr = xstream.toXML(student);  
    System.out.println(xmlStr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    序列化之后

    <Student>
      <name>pli</name>
      <age>18</age>
    </Student>
    
    • 1
    • 2
    • 3
    • 4

    也可以通过xstream.aliasField("NAME", String.class, "name");来指定字段别名

    1. 注解形式

    Student类

    @XStreamAlias("PERSON")  
    public class Student {  
      
        @XStreamAlias("NAME")  
        private String name;  
        @XStreamAlias("AGE")  
        private int age;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    主类方法

    XStream xstream = new XStream();
    // 设置自动处理全部注解,或处理指定注解,二选一即可
    //xstream.autodetectAnnotations(true);  
    xstream.processAnnotations(Student.class);  
    Student student = new Student();  
    student.setName("pli");  
    student.setAge(18);  
    String xmlStr = xstream.toXML(student);  
    System.out.println(xmlStr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    序列化结果:

    <PERSON>
      <NAME>pli</NAME>
      <AGE>18</AGE>
    </PERSON>
    
    • 1
    • 2
    • 3
    • 4
    1. 为什么推荐使用注解形式?
      我想你也注意到了,使用注解可以很方便的改变属性的名称格式。所以原因有如下
      Java bean 的属性命名格式为驼峰形式,而xml的节点命名为全大写。这种情况下,要想所有的属性都能和xml报文对上,使用注解无疑更加合理。
      例如:
    XStream xstream = new XStream();  
    xstream.alias(Student.class.getSimpleName().toUpperCase(), Student.class);  
      
    String xmlStr2 = "<PERSON>\n" +  
                    "  <NAME>pli</NAME>\n" +  
                    "  <AGE>18</AGE>\n" +  
                    "</PERSON>";  
    Student student1 = (Student) xstream.fromXML(xmlStr2);  
    System.out.println(student1.toString());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    尽管指定了别名,但是对于大写的属性和类属性名称无法对应,执行报异常
    在这里插入图片描述

    此时,如果使用注解,就可以轻松完成字段的映射。

    JAXB

    JAXB 其实就是注解版的 XStream,JAXB提供了自己的一套注解,通过注解来完成 Java bean 和 xml 节点之间的映射。

    JAXBContext context = JAXBContext.newInstance(Teacher.class);  
    Teacher teacher = new Teacher();  
    teacher.setName("pli");  
    teacher.setAge(18);  
    Marshaller marshaller = context.createMarshaller();  
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);  
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");  
    StringWriter writer = new StringWriter();  
    marshaller.marshal(teacher, writer);  
    String jaxbStr = writer.toString();  
    System.out.println(jaxbStr);  
      
    Unmarshaller unmarshaller = context.createUnmarshaller();  
    Teacher t1 = (Teacher) unmarshaller.unmarshal(new StringReader(jaxbStr));  
    System.out.println(t1.toString());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    输出结果如下:
    在这里插入图片描述

    总结

    1. 推荐使用JAXB作为转换工具
    • 作为jdk原生的工具,JAXB 提供了更好的兼容性
    • XStream 在反序列化时,有代码注入风险(具体没有验证过)
    • JAXB 能自动添加和解析 xml 头部,省去了处理 xml 头部的功夫
    1. XStream 在使用时,一定要注意创建的实例。因为xstream的配置都是在实例上,如果重新创建了实例,那之前设置的属性都将失效。
  • 相关阅读:
    Lock的学习与使用
    入门力扣自学笔记193 C++ (题目编号:1668)
    阿里云主要产品有哪些?有什么用?
    十九章总结
    110道 MySQL面试题及答案 (持续更新)
    个股与指数行情走势对比分析 !股票量化分析工具QTYX-V2.5.2
    100000开发的系统,执意重构钱多执念?
    音乐播放器开发实例(可毕设)
    什么是方法,什么是方法论:了解自我精进提升的底层逻辑
    Kotlin 实现自定义下拉阴影弹窗的功能
  • 原文地址:https://blog.csdn.net/qq_42389764/article/details/125506439