由于篇幅有限,此处生出源代码,如有需要的在评论里面留下联系的方式,笔者到时联系你。转载请标明读者链接,谢谢。
一.JAXB简介
JAXB
是
CXF
一个默认的数据绑定,如果你不指定其他数据绑定在你的
Spring
配置中或者在
API
,你可以得到
JAXB
的数据绑定。自从
2.3.x
版本以后默认的使用
JAXB2.2
,
maven
使用者运行在
jdk6
之上将需要使用
java
认证的重写机制来使用
JAXB2.2
来替代
JAXB2.1
。
JAXB
使用
java
注解结合文件路径在
XML
和
Java
之间构建映射。
JAXB
支持编码优先和架构优先编程。架构优先支持创建客户代理、动态、运行时。详解见
CXF
的
DynamicClientFactory
类。
CXF
使用
JAXB
引用实现。为了学习更多关于注解类或者怎样把一个
schema
生成实体类,详见官网。
二. 解组和编组
解组:(
unmarshalling
)把数据从存储媒介上转化到内存中的过程,正好与编组相反。因此需要把
xml
文档解组到
Java VM
中。这里的复杂性不是在扁平数据中,因为这不是必需的,而在于从正确的数据到正确
Java
代码变量的映射。如果映射是错误的,就不可能正确的访问数据。当然,如果再尝试重新编组还会造成更大的问题,并且问题传播的很快。
编组:<!-- [if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]-->(
marshalling
)是把内存中的数据转化到存储媒介上的过程。因此在
java
和
XML
环境中,编组就是把一些
Java
对象转换成一个或多个
XML
文档。在数据库环境中,则是把
Java
表示的数据存入数据库。显然,编组的秘密在于把
Java
实例中的面向对象结构转化成适用于
XML
的扁平结构,或者
RDBMS
中的关系结构。
三.代码以及分析
首先需要加入cxf所需要的包,在本次测试中,笔者添加了cxf的lib中全部的包。
下面直接上代码:
package com.syc.jaxb;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlJavaTypeAdapter(UserAdapter.class)
public interface User {
String getName();
}
此处注释的XmlJavaTypeAdapter是对自定义编组使用实现XmlAdapter的适配器,即UserAdapter这个类,该类实现了XmlAdapter适配器,因此要实现解组和编组两个方法。可能有的初学读者会提到:为什么我们要实现编组和解组呢?原因很简单,CXF不能直接支持List、Map等。
package com.syc.jaxb;
import javax.xml.bind.annotation.XmlType;
@XmlType(name="User")
public class UserImpl implements User{
String name;
public UserImpl(){}
public UserImpl(String n){
this.name =n;
}
@Override
public String getName() {
return name;
}
public void setName(String n){
this.name = n ;
}
}
该类是实现了User接口,并且重写getName()方法,此类可以看成一个User实体类,其实也没有什么区别。这里注释的XmlType是将UserImpl映射到 XML 模式类型,即我们得到的客户端的时候显示的类的名字是User。
package com.syc.jaxb;
import java.util.Map;
import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@WebService
public interface HelloWorld {
String sayHi(String text);
String sayHiToUser(User user);
@XmlJavaTypeAdapter(UserMapAdapter.class)
Map<Integer,User> getUsers();
}
该接口是暴露的服务,该服务有三个方法,暴露的服务必须使用@WebService注释,不然在发布服务的时候找不到不要发布的服务类。由于第三个方法返回的是一个Map类型,但
JAXB
不能将一些
Java
类型自然映射到
XML
表示形式,例如
,HashMap
或者其他非
JavaBean
类。如参数类型为接口,以及
Map
,这需要特殊的
XmlAdapter
类进行处理。因此这里我们需要注释成让XmlAdapter适配器来处理。
package com.syc.jaxb;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.jws.WebService;
@WebService(endpointInterface="com.syc.jaxb.HelloWorld",
serviceName="HelloWorld")
public class HelloWorldImpl implements HelloWorld {
Map<Integer,User> users = new LinkedHashMap<Integer, User>();
@Override
public String sayHi(String text) {
System.out.println("sayHello called...");
return "Hello " +text;
}
@Override
public String sayHiToUser(User user) {
System.out.println("sayUserHello called...");
users.put(users.size()+1, user);
return "Hello"+ user.getName();
}
@Override
public Map<Integer, User> getUsers() {
System.out.println("getMapUsers called...");
return users;
}
}
该类是服务类的一个实现。
package com.syc.jaxb;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class UserAdapter extends XmlAdapter<UserImpl, User>{
@Override
public User unmarshal(UserImpl v) throws Exception {
return v;
}
@Override
public UserImpl marshal(User v) throws Exception {
if(v instanceof UserImpl){
return (UserImpl)v;
}
return new UserImpl(v.getName());
}
}
在这里,UserImpl是value类型,User是alue类型。UserAdapter类继承了XmlAdapter类,因此需要重写marshal()和unmarshal()方法,即编组和解组,在此处,编组就是将bound类型修改为value类型,然后将value类型编组为xml表示形式;解组就是JAXB绑定框架首先将XML表示形式解组为value类型,然后将value类型修改为bound类型。在这里我们可以这么理解,编组即bound->value->xml形式,解组即xml形式->value->bound。
package com.syc.jaxb;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlType(name="UserMap")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserMap {
@XmlElement(nillable=false,name="entry")
List<UserEntry> entries = new ArrayList<UserEntry>();
public List<UserEntry> getEntries() {
return entries;
}
public void addEntry(UserEntry entry){
entries.add(entry);
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="UserEntry")
static class UserEntry{
public UserEntry(){
super();
}
public UserEntry(Map.Entry<Integer, User> entry){
super();
this.id = entry.getKey();
this.user = entry.getValue();
}
public UserEntry(Integer id,User user){
super();
this.id = id;
this.user = user;
}
@XmlElement(required=true,nillable=false)
Integer id;
User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
}
UserMap类是让cxf支持MAP的关键,该类可以将map里面的key-value转换为User实体类,把key当作user的id值,把value当作user的name值,然后再把user保存到一个集合中,即实现了hash值到实体类的转换。
package com.syc.jaxb;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class UserMapAdapter extends XmlAdapter<UserMap, Map<Integer,User>>{
@Override
public Map<Integer, User> unmarshal(UserMap v) throws Exception {
Map<Integer, User> map = new LinkedHashMap<Integer, User>();
for(UserMap.UserEntry e : v.getEntries()){
map.put(e.getId(), e.getUser());
}
return map;
}
@Override
public UserMap marshal(Map<Integer, User> v) throws Exception {
UserMap map = new UserMap();
for(Map.Entry<Integer, User> e : v.entrySet()){
UserMap.UserEntry u = new UserMap.UserEntry();
u.setId(e.getKey());
u.setUser(e.getValue());
map.getEntries().add(u);
}
return map;
}
}
这里即对UserMap和Map对象的编组和解组。
package com.syc.jaxb;
import javax.xml.ws.Endpoint;
public class Server {
public static void main(String[] args) {
System.out.println("Starting Server... ");
String address = "http://localhost:8899/hello";
HelloWorldImpl implementor = new HelloWorldImpl();
Endpoint.publish(address, implementor);
try {
Thread.sleep(5*60*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Exiting Server... ");
System.exit(0);
}
}
用WSDL2JAVA生成的客户端,调用服务端代码
package com.syc.jaxb.client;
import java.util.List;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class HelloClient {
public static void main(String[] args) {
JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
factoryBean.setAddress("http://localhost:8899/hello");
factoryBean.setServiceClass(HelloWorld.class);
HelloWorld h = (HelloWorld) factoryBean.create();
System.out.println(h.sayHi("shenyc"));
User u = new User();
u.setName("syc");
System.out.println(h.sayHiToUser(u));
User u1 = new User();
u1.setName("ssss");
System.out.println(h.sayHiToUser(u1));
User u2 = new User();
u2.setName("aaaaa");
System.out.println(h.sayHiToUser(u2));
UserMap users = h.getUsers();
List<UserEntry> list = users.getEntry();
for(UserEntry ue : list){
System.out.println(ue.getId()+":"+ue.getUser().getName());
}
}
}
分享到:
相关推荐
本主题将深入探讨CXF如何处理像Map这样的Java集合类,以及其他不能直接通过标准XML Schema(如XSD)表示的复杂数据结构。 **一、CXF与复杂类型** 1. **XML与复杂类型映射**:CXF使用JAXB(Java Architecture for ...
Aegis数据绑定支持基本的数据类型、集合、Map以及自定义的Java类,为开发者提供了一种灵活的方式来处理Java对象和服务之间的转换。 以下是使用Apache CXF结合Spring发布Web Services(Aegis数据绑定)的基本步骤: ...
4. **数据绑定配置**:为了使CXF能够识别和使用我们的自定义JAXB类,我们需要在CXF的配置中指定数据绑定。这通常在服务的XML配置文件或者通过Java代码进行。 5. **使用CXF扩展**:CXF提供了许多扩展点,如...
【标题】"cxf开发map的demo"是一个关于使用Java CXF框架处理Map类型数据的实战示例。CXF是一个开源服务框架,它允许开发者创建和消费Web服务,支持多种协议和绑定,包括SOAP、RESTful等。在这个demo中,我们将深入...
在实际应用中,我们需要在CXF服务端创建服务接口和实现,然后通过JAXB(Java Architecture for XML Binding)进行数据绑定。JAXB会自动将Java对象转换为XML,反之亦然。在服务接口中,可以定义如下的方法: ```java...
Apache CXF入门范例以及对传递ListMap类型的疑惑】中,可能会详细解释如何创建和调用一个使用CXF的Web服务,同时也可能讨论了在处理复杂数据类型如List<Map, Object>>时遇到的问题和解决方案。通常,CXF允许你通过...
`XmlAdapter`是JAXB(Java Architecture for XML Binding)的一部分,用于处理JAXB不能直接绑定的数据类型。 - `MapAdapter`有两个主要方法:`unmarshal`和`marshal`。`unmarshal`方法负责将从XML解析得到的`...