在Spring OXM-XStream快速入门 的案例中,我们看到生成的xml报文如下:
<com.xgj.oxm.xstream.quickDemo.domain.User>
1
Artisan
artisan
1000
2017-12-05 07:30:46.772 UTC
<com.xgj.oxm.xstream.quickDemo.domain.LoginLog>
99
1
127.0.0.1
2017-12-05 07:30:46.772 UTC
com.xgj.oxm.xstream.quickDemo.domain.LoginLog>
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)
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)设置类成员别名 1 改为1
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中的标记
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>1userId>
<userName>ArtisanuserName>
<password>artisanpassword>
<credits>1000credits>
<lastVisit>2017-12-05 13:39:32.698 UTClastVisit>
<loginLog id="1">
<loginLogId>99loginLogId>
<ip>127.0.0.1ip>
<loginDate>2017-12-05 13:39:32.698 UTCloginDate>
loginLog>
<loginLog id="2">
<loginLogId>22loginLogId>
<ip>192.168.1.1ip>
<loginDate>2017-12-05 13:39:32.698 UTCloginDate>
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中的标记。
假设我们有如下的XML,我们如何使用XStream去读写呢?
<blog author="Guilherme Silveira">
<entry>
<title>firsttitle>
<description>My first blog entry.description>
entry>
<entry>
<title>tutorialtitle>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
description>
entry>
blog>
结合XStream中的方法,我们来分析一下
接下来我们来看下我们创建的几个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 entries = new ArrayList();
/**
*
*
* @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
*/
public List 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方法,可根据需要创建。
接下来,我们来测试一下
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>
Guilherme Silveira
<com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
first
My first blog entry.
com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
<com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
tutorial
Today we have developed a nice alias tutorial. Tell your friends! NOW!
com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Entry>
com.xgj.oxm.xstream.quickDemo.aliasDemo.officeDemo.Blog>
我们需要把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 Silveiraname>
writer>
<entries>
<entry>
<title>firsttitle>
<description>My first blog entry.description>
entry>
<entry>
<title>tutorialtitle>
<description>Today we have developed a nice alias tutorial. Tell your friends! NOW!description>
entry>
entries>
blog>
下面把wirter转换为 author .通过
xstream.aliasField("author", Blog.class, "writer");
输出如下
<blog>
<author>
<name>Guilherme Silveiraname>
author>
<entries>
<entry>
<title>firsttitle>
<description>My first blog entry.description>
entry>
<entry>
<title>tutorialtitle>
<description>Today we have developed a nice alias tutorial. Tell your friends! NOW!description>
entry>
entries>
blog>
去掉entries节点,通过
xstream.addImplicitCollection(Blog.class, "entries");
输出如下
<blog>
<author>
<name>Guilherme Silveiraname>
author>
<entry>
<title>firsttitle>
<description>My first blog entry.description>
entry>
<entry>
<title>tutorialtitle>
<description>Today we have developed a nice alias tutorial. Tell your friends! NOW!description>
entry>
blog>
下一步是将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>firsttitle>
<description>My first blog entry.description>
entry>
<entry>
<title>tutorialtitle>
<description>Today we have developed a nice alias tutorial. Tell your friends! NOW!description>
entry>
blog>
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 Silveiraname>
writer>
<entries>
<com.artisan.Entry>
<title>firsttitle>
<description>My first blog entry.description>
com.artisan.Entry>
<com.artisan.Entry>
<title>tutorialtitle>
<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