Spring OXM-XStream使用别名

简介: Spring OXM-XStream使用别名

导读


Spring OXM-XStream快速入门 的案例中,我们看到生成的xml报文如下:


<com.xgj.oxm.xstream.quickDemo.domain.User>
  <id>1</id>
  <userName>Artisan</userName>
  <password>artisan</password>
  <credits>1000</credits>
  <lastVisit>2017-12-05 07:30:46.772 UTC</lastVisit>
  <logs>
    <com.xgj.oxm.xstream.quickDemo.domain.LoginLog>
      <loginLogId>99</loginLogId>
      <userId>1</userId>
      <ip>127.0.0.1</ip>
      <loginDate>2017-12-05 07:30:46.772 UTC</loginDate>
    </com.xgj.oxm.xstream.quickDemo.domain.LoginLog>
  </logs>
</com.xgj.oxm.xstream.quickDemo.domain.User>


在默认情况下,Java对象到XML的映射是Java对象属性名对应XML的元素名,Java类的全名对应XML根元素的名字。

事实上,在实际应用中,如果XML和Java类都已经存在相应的名称,那么在进行转换时,需要设置别名进行映射。


别名配置的三种情况


类别名: 使用alias(String name,Class type)


类成员别名:使用aliasField(String alias, Class definedIn, String fieldName)


类成员作为xml属性别名:使用aliasAttribute(Class definedIn, String attributeName, String alias)方法。 并且需要通过 useAttributeFor(Class definedIn, String fieldName) 应用到某个类上。

从上面的实例中我们看到XML元素结构不是很友好,接下来我们通过XStream提供的别名机制来修饰生成的XML元素的结构。

package com.xgj.oxm.xstream.quickDemo.aliasDemo;
import java.text.ParseException;
import java.util.Date;
import com.thoughtworks.xstream.XStream;
import com.xgj.oxm.xstream.quickDemo.domain.LoginLog;
import com.xgj.oxm.xstream.quickDemo.domain.User;
public class XStreamAliasDemo {
    private static XStream xstream;
    static {
        // 创建一个Xstream实例,使用默认的XPP解析器
        xstream = new XStream();
        // (1)设置类别名,修改默认的全限定名的名称
        xstream.alias("user", User.class);
        xstream.alias("loginLog", LoginLog.class);
        // (2)设置类成员别名 <id>1</id> 改为<userId>1</userId>
        xstream.aliasField("userId", User.class, "id");
        // (3)把LoginLog的userId属性视为xml属性,默认为xml的元素
        xstream.aliasAttribute(LoginLog.class, "userId", "id");
        xstream.useAttributeFor(LoginLog.class, "userId");
        // (4)去掉集合类型生成XML的父节点,即忽略xml中的<logs></logs>标记
        xstream.addImplicitCollection(User.class, "logs");
    }
    /**
     * 
     * 
     * @Title: getUser
     * 
     * @Description: 初始化转换对象
     * 
     * @return
     * 
     * @return: User
     * @throws ParseException
     */
    public static User getUser() throws ParseException {
        LoginLog log = new LoginLog();
        log.setIp("127.0.0.1");
        log.setLoginLogId(99);
        log.setUserId(1);
        log.setLoginDate(new Date());
        LoginLog log2 = new LoginLog();
        log2.setIp("192.168.1.1");
        log2.setLoginLogId(22);
        log2.setUserId(2);
        log2.setLoginDate(new Date());
        User user = new User();
        user.setId(1);
        user.setUserName("Artisan");
        user.setPassword("artisan");
        user.setCredits(1000);
        user.setLastVisit(new Date());
        user.addLoginLog(log);
        user.addLoginLog(log2);
        return user;
    }
    /**
     * 
     * 
     * @Title: objectToXml
     * 
     * @Description: Java对象转换成XML
     * 
     * @throws Exception
     * 
     * @return: void
     */
    public static void objectToXml() throws Exception {
        // 获取转换的User对象实例
        User user = getUser();
        // 输出内容到控制台,查看一下
        System.out.println(xstream.toXML(user));
        System.out.println("objectToXml successfully");
    }
    public static void main(String[] args) throws Exception {
        objectToXml();
    }
}


输出

<user>
  <userId>1</userId>
  <userName>Artisan</userName>
  <password>artisan</password>
  <credits>1000</credits>
  <lastVisit>2017-12-05 13:39:32.698 UTC</lastVisit>
  <loginLog id="1">
    <loginLogId>99</loginLogId>
    <ip>127.0.0.1</ip>
    <loginDate>2017-12-05 13:39:32.698 UTC</loginDate>
  </loginLog>
  <loginLog id="2">
    <loginLogId>22</loginLogId>
    <ip>192.168.1.1</ip>
    <loginDate>2017-12-05 13:39:32.698 UTC</loginDate>
  </loginLog>
</user>


说明:


在(1)处,通过XStream的alias方法来设置类别名。


在(2)处,通过XStream的aliasField方法将User类的id属性设置为userId


在(3)处,通过XStream的aliasAttribute和useAttributeFor方法将LoginLog类的userId属性设置为id,并设置为LoginLog元素的属性。 默认为LoginLog元素的子元素。


在(4)处,通过XStream的addImplicitCollection方法删除集合节点logs,即忽略XML中的<logs></logs>标记。


官方Demo

问题

假设我们有如下的XML,我们如何使用XStream去读写呢?

<blog author="Guilherme Silveira">
  <entry>
    <title>first</title>
    <description>My first blog entry.</description>
  </entry>
  <entry>
    <title>tutorial</title>
    <description>
        Today we have developed a nice alias tutorial. Tell your friends! NOW!
    </description>
  </entry>
</blog>


结合XStream中的方法,我们来分析一下


blog 节点有个 author 属性 ,可以使用aliasAttribute 和 useAttributeFor方法应用到Blog类上,也可以使用XStream的转换器,这里我们使用转换器的方式。 因为要使用转换器,所以需要一个Author类以及对应的一个name属性用于存储name的值


子节点是多个entry,可以使用List来存储


entry节点有title 和 description 属性 ,所以需要一个Entry类以及2个属性


Model

接下来我们来看下我们创建的几个model类

package com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo;
import java.util.ArrayList;
import java.util.List;
public class Blog {
    // Author
    private Author writer;
    // Entry集合
    private List<Entry> entries = new ArrayList<Entry>();
    /**
     * 
     * 
     * @Title:Blog
     * 
     * @Description:构造函数
     * 
     * @param writer
     */
    public Blog(Author writer) {
        this.writer = writer;
    }
    /**
     * 
     * 
     * @Title: add
     * 
     * @Description: 添加Entry
     * 
     * @param entry
     * 
     * @return: void
     */
    public void add(Entry entry) {
        entries.add(entry);
    }
    /**
     * 
     * 
     * @Title: getContent
     * 
     * @Description: 获取Entry List集合
     * 
     * @return
     * 
     * @return: List<Entry>
     */
    public List<Entry> getContent() {
        return entries;
    }
}


package com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo;
public class Author {
    private String name;
    public Author(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
package com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo;
public class Entry {
    private String title, description;
    public Entry(String title, String description) {
        this.title = title;
        this.description = description;
    }
}


我们没有创建set/get方法,可根据需要创建。


A Simple Test

接下来,我们来测试一下


public static void main(String[] args) {
        Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
        teamBlog.add(new Entry("first","My first blog entry."));
        teamBlog.add(new Entry("tutorial",
                "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
        XStream xstream = new XStream();
        System.out.println(xstream.toXML(teamBlog));
}

输出如下

<com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Blog>
  <writer>
    <name>Guilherme Silveira</name>
  </writer>
  <entries>
    <com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
      <title>first</title>
      <description>My first blog entry.</description>
    </com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
    <com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
      <title>tutorial</title>
      <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
    </com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
  </entries>
</com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Blog>


Class aliasing

我们需要把com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Blog 和com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry 转换成 blog 和 entry.

通过

    xstream.alias("blog", Blog.class);
    xstream.alias("entry", Entry.class);


Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
        teamBlog.add(new Entry("first", "My first blog entry."));
        teamBlog.add(new Entry("tutorial",
                "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
        XStream xstream = new XStream();
        // alias Class
        xstream.alias("blog", Blog.class);
        xstream.alias("entry", Entry.class);
        System.out.println(xstream.toXML(teamBlog));

输出结果如下

<blog>
  <writer>
    <name>Guilherme Silveira</name>
  </writer>
  <entries>
    <entry>
      <title>first</title>
      <description>My first blog entry.</description>
    </entry>
    <entry>
      <title>tutorial</title>
      <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
    </entry>
  </entries>
</blog>


Field aliasing

下面把wirter转换为 author .通过

xstream.aliasField("author", Blog.class, "writer");


输出如下

<blog>
  <author>
    <name>Guilherme Silveira</name>
  </author>
  <entries>
    <entry>
      <title>first</title>
      <description>My first blog entry.</description>
    </entry>
    <entry>
      <title>tutorial</title>
      <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
    </entry>
  </entries>
</blog>


Implicit Collections

去掉entries节点,通过

xstream.addImplicitCollection(Blog.class, "entries");


输出如下

<blog>
  <author>
    <name>Guilherme Silveira</name>
  </author>
  <entry>
    <title>first</title>
    <description>My first blog entry.</description>
  </entry>
  <entry>
    <title>tutorial</title>
    <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
  </entry>
</blog>


Attribute aliasing


下一步是将writer成员变量转换为xml的属性 , 为了做到这一点,我们需要告诉XStream将Blog#writer字段同义为author


问题 : how does XStream converts an Author in a String so it can be written as a XML tag attribute?


Attributes cannot be written for types that are handled by Converter implementations, we have to use a SingleValueConverter and implement our own converter for the Author:

package com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo;
import com.thoughtworks.xstream.converters.SingleValueConverter;
public class AuthorConverter implements SingleValueConverter {
    /**
     * tells XStream which types it can deal with
     */
    public boolean canConvert(Class type) {
        return type.equals(Author.class);
    }
    /**
     * extract a String from an Author
     */
    public String toString(Object obj) {
        return ((Author) obj).getName();
    }
    /**
     * takes a String and returns an Author
     */
    public Object fromString(String name) {
        return new Author(name);
    }
}


然后注册转换器

xstream.useAttributeFor(Blog.class, "writer");
xstream.registerConverter(new AuthorConverter());


完整的代码如下

package com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo;
import com.thoughtworks.xstream.XStream;
public class AliasTest {
    public static void main(String[] args) {
        Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
        teamBlog.add(new Entry("first", "My first blog entry."));
        teamBlog.add(new Entry("tutorial",
                "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
        XStream xstream = new XStream();
        xstream.alias("blog", Blog.class);
        xstream.alias("entry", Entry.class);
        xstream.aliasField("author", Blog.class, "writer");
        xstream.addImplicitCollection(Blog.class, "entries");
        xstream.useAttributeFor(Blog.class, "writer");
        xstream.registerConverter(new AuthorConverter());
        System.out.println(xstream.toXML(teamBlog));
    }
}


输出

<blog author="Guilherme Silveira">
  <entry>
    <title>first</title>
    <description>My first blog entry.</description>
  </entry>
  <entry>
    <title>tutorial</title>
    <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
  </entry>
</blog>



Package aliasing

xstream.aliasPackage("my.company", "org.thoughtworks");


比如

package com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo;
import com.thoughtworks.xstream.XStream;
public class AliasPackage {
    public static void main(String[] args) {
        Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
        teamBlog.add(new Entry("first", "My first blog entry."));
        teamBlog.add(new Entry("tutorial",
                "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
        XStream xstream = new XStream();
        xstream.aliasPackage(
"com.artisan",
                "com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo");
        System.out.println(xstream.toXML(teamBlog));
    }
}


输出

<com.artisan.Blog>
  <writer>
    <name>Guilherme Silveira</name>
  </writer>
  <entries>
    <com.artisan.Entry>
      <title>first</title>
      <description>My first blog entry.</description>
    </com.artisan.Entry>
    <com.artisan.Entry>
      <title>tutorial</title>
      <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
    </com.artisan.Entry>
  </entries>
</com.artisan.Blog>


示例源码


代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

相关文章
|
XML JavaScript Java
Spring OXM-XStream流化对象
Spring OXM-XStream流化对象
92 0
|
XML 缓存 Java
Spring OXM-XStream注解
Spring OXM-XStream注解
113 0
|
XML Java 数据格式
Spring OXM-XStream转换器
Spring OXM-XStream转换器
62 0
|
XML 存储 JavaScript
Spring OXM-XStream快速入门
Spring OXM-XStream快速入门
106 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
167 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
13天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
26 2
 SpringBoot入门(7)- 配置热部署devtools工具
|
9天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
21 2
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
54 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
下一篇
无影云桌面