CXF默认使用JAXB 来实现对象和XML之间的映射。在前面的例子 中,使用CXF发布的Webservice,其方法的参数和返回值都是简单类型。 本文讨论对象复杂性的分级,验证对于各种复杂度JAXB的支持情况,以及使用JAXB时对于Map,循环引用,继承等情况的处理办法。 文中的例子没有直接调用JAXB的API,而是用CXF发布webservice的形式验证对象到xml的marshal和unmarshal, 所以本文也可以作为使用CXF的参考资料。
1 数据复杂性的分类
大体来说,Java中的数据/数据对象按照其复杂度可以分为以下几类:
1.1 简单数据类型
包括基本类型和Java对基本类型的封装,主要有:
基本类型封装类
float
Float
double
Double
byte
Byte
short
Short
int
Integer
long
Long
char
Character
boolean
Boolean
char[]
String
1.2 自定义类型
在C里面叫做struct,在Java里面叫做JavaBean,包含自定义属性和getter/setter方法。
1.3 集合类型
Java的集合类(Collection)主要分为List,Set,Map三个系列。List实现了元素的序列(顺序),Set实现不重复的集合,Map实现了key-value的映射。
1.4 复杂类型
更复杂的情况是对于上述三种类型的组合运用,比如在自定义类型中使用集合,或者集合的嵌套等。 复杂类型还会涉及到循环引用和继承关系等问题。
2 JAXB对数据复杂性的支持
简单类型
对于简单的数据类型,JAXB不需要任何处理就完全能够支持
自定义类型
JAXB对于一般的JavaBean也能够支持,比如下面的例子:
User.java
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
不需要JavaBean实现Serializable接口,也不需要增加@XmlRootElement声明。
集合类型
JAXB能够内置支持List和Set集合,但是对于Map的支持需要自己处理。
复杂类型
JAXB支持简单类型、自定义类型、集合类型等的嵌套,但是对于循环引用、继承等情况需要增加额外的处理。
3 常用技巧
3.1 使用自定义的XmlAdapter支持Map
JAXB可以在变量上添加@XmlJavaTypeAdapter标注,指定对该变量专门的适配器进行处理。 适配器继承XmlAdapter类,并覆盖了marshal和unmarshal方法,分别用于对象到XML的映射和XML到对象的映射。
使用XmlAdapter可以实现对Map类型的映射。
比如对于要通过CXF发布的WebService接口方法上,可以增加标注:
@XmlJavaTypeAdapter(MapAdapter.class)
Map getUserMap();
Integer setUserMap(@XmlJavaTypeAdapter(MapAdapter.class)Map users);
其中的MapAdapter就是自己实现的Map适配器,代码如下:
MapAdapter.java
MapEntity是自己定义的一个简单结构,用于保持Map中的key-value关系:
MapEntity.java
public classMapEntity{
publicObject key;
publicObject value;
}
经过这样的处理,就能够实现Map与XML之间的映射。
3.2 断开循环引用的回路
对象之间的引用很有可能出现回路。最简单的情况是两个对象之间互相引用。这在ORM中很常见。如果我们在前面的User类中增加父子关系,如下: