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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值