之前说过,对于当形参、返回值的类型是String、基本数据类型、JavaBean式的复合类,List集合,数组的时候,CXF可以很好的处理。但是像Map、非JavaBean式的复合类,CXF是处理不了的。
我们先用之前编写的示例实验一下。
我们在服务端的HelloWorld接口中增加一个getAllCats()方法,返回一个Map集合:
package org.java.cxf.ws;
import java.util.List;
import java.util.Map;
import javax.jws.WebService;
import org.java.cxf.domain.Cat;
import org.java.cxf.domain.User;
@WebService
public interface HelloWorld {
public String sayHi(String name);
public List<Cat> getCatsByUser(User user);
public Map<String,Cat> getAllCats();
}
在实现类中编写该方法:
package org.java.cxf.ws.impl;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.jws.WebService;
import org.java.cxf.domain.Cat;
import org.java.cxf.domain.User;
import org.java.cxf.ws.HelloWorld;
import org.java.cxf.ws.UserService;
@WebService(endpointInterface="org.java.cxf.ws.HelloWorld"
,serviceName="HelloworldWs")
public class HelloworldWs implements HelloWorld{
@Override
public String sayHi(String name) {
return name+",您好"
+"现在的时间是:"+new Date();
}
@Override
public List<Cat> getCatsByUser(User user) {
//在实际项目中,Web Service组件自己并不会去实现业务功能
//它只是调用业务逻辑组件的方法来暴露Web Service
UserService us=new UserServiceImpl();
return us.getCatsByUser(user);
}
@Override
public Map<String, Cat> getAllCats() {
UserService us=new UserServiceImpl();
return us.getAllCats();
}
}
然后在UserService接口声明该方法
package org.java.cxf.ws;
import java.util.List;
import java.util.Map;
import org.java.cxf.domain.Cat;
import org.java.cxf.domain.User;
public interface UserService {
public List<Cat> getCatsByUser(User user);
public Map<String, Cat> getAllCats();
}
实现类UserServiceImpl中实现getAllCats()方法:
package org.java.cxf.ws.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.java.cxf.domain.Cat;
import org.java.cxf.domain.User;
import org.java.cxf.ws.UserService;
public class UserServiceImpl implements UserService {
//用一个HashMap来模拟内存中的数据库
static Map<User,List<Cat>> catDb=new HashMap<>();
//初始化数据
static{
List<Cat> CatList1=new ArrayList<Cat>();
CatList1.add(new Cat(1,"花花","黑色"));
CatList1.add(new Cat(2,"毛球","白色"));
catDb.put(new User(1,"zhangsan","1122","河南"), CatList1);
List<Cat> CatList2=new ArrayList<Cat>();
CatList2.add(new Cat(3,"丁丁","黄色"));
CatList2.add(new Cat(4,"咪咪","灰色"));
catDb.put(new User(1,"lisi","3344","广州"), CatList2);
}
public List<Cat> getCatsByUser(User user) {
return catDb.get(user);
}
@Override
public Map<String, Cat> getAllCats() {
Map<String ,Cat> result =new HashMap<String,Cat>();
int i=1;
for(List<Cat> cats:catDb.values()){
for(Cat cat:cats){
result.put("第"+ i++ +"个", cat);
}
}
return result;
}
}
我们重新启动服务端:
发现分别报了javax.xml.ws.WebServiceException和 javax.xml.bind.JAXBException这两个错误。也就是说Map这种类型是CXF接受不了的数据格式。
那么,在CXF开发中,如果遇到系统无法自动处理的类型,就需要开发人员自行处理了。
处理思路:提供一个转换器,该转换器负责把CXF搞不定的类型,转换成其搞的定的类型。
处理步骤:
(1)使用@XmlJavaTypeAdapter(Java类型适配器注解)修饰CXF无法自动处理的类型。使用该注解时,需要给注解指定一个适配器值。
package org.java.cxf.ws;
import java.util.List;
import java.util.Map;
import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.java.cxf.domain.Cat;
import org.java.cxf.domain.User;
@WebService
public interface HelloWorld {
public String sayHi(String name);
public List<Cat> getCatsByUser(User user);
//CXF不能处理这种类型,所以采用XmlJavaTypeAdapter来处理
public @XmlJavaTypeAdapter(value = WSXmlAdapter.class)
Map<String,Cat> getAllCats();
}
(2)实现自己的适配器,然后编写一个CXF识别的数据类型:
package org.java.cxf.ws;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.java.cxf.domain.Cat;
import org.java.cxf.ws.StringCat.Entry;
//XmlAdapter<ValueType, BoundType>接口参数中ValueType是CXF可以解析的类型
//BoundType是CXF搞不定的类型
public class WSXmlAdapter extends XmlAdapter<StringCat, Map<String,Cat>>{
@Override
public Map<String, Cat> unmarshal(StringCat v) throws Exception {
Map<String,Cat> result=new HashMap<>();
for(Entry entry:v.getEntries()){
result.put(entry.getKey(), entry.getValue());
}
return result;
}
@Override
public StringCat marshal(Map<String, Cat> v) throws Exception {
StringCat cCat=new StringCat();
for(String key:v.keySet()){
cCat.getEntries().add(new Entry(key,v.get(key)));
}
return cCat;
}
}
其中StringCat类为:
package org.java.cxf.ws;
import java.util.ArrayList;
import java.util.List;
import org.java.cxf.domain.Cat;
public class StringCat {
//静态内部类
public static class Entry{
private String key;
private Cat value;
public Entry(){}
public Entry(String key, Cat value) {
this.key=key;
this.value=value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Cat getValue() {
return value;
}
public void setValue(Cat value) {
this.value = value;
}
}
private List<Entry> entries=new ArrayList<Entry>();
public List<Entry> getEntries() {
return entries;
}
public void setEntries(List<Entry> entries) {
this.entries = entries;
}
}
然后我们的程序就完成了,我们重启服务端看一下:
我们的服务重启成功。
我们分析一下发布成功时的WSDL文档:
整个wsdl文档没有什么变化,只是比之前多了一个getAllCats的operation。
我们去看一下import标签中的location的路径,之前说过,这个是引入的接口的定义文档:
我们看到这里也没有什么大的变化,仅仅是多了getAllCats的message。
我们去看一下types标签对的import标签中的schemaLocation,这是引入的类型的定义文档:
从中我们可以看出我们定义的StringCat数据类型的定义,证明我们对外发布的getAllCats方法的返回类型是StringCat。
即是,对于getAllCats操作来说,
传入的消息是
<getAllCats>
</getAllCats>
传出的消息是
<getAllCatsResponse>
<return>
<entries>
<key>字符串</key>
<value>
<color>字符串</color>
<id>整数值</id>
<name>字符串</name>
</value>
</entries>
</return>
</getAllCatsResponse>
我们在客户端的源代码文件夹重新生成WebService相关代码:
然后我们刷新客户端工程:
我们在客户端的主类中调用getAllCats方法,获取所有的Cat:
package show;
import org.java.cxf.ws.Entry;
import org.java.cxf.ws.HelloWorld;
import org.java.cxf.ws.StringCat;
import org.java.cxf.ws.impl.HelloworldWs;
public class ClientMain {
public static void main(String[] args) {
HelloworldWs factory=new HelloworldWs();
//此处返回的只是远程Web Service的代理
HelloWorld hw=factory.getHelloworldWsPort();
System.out.println(hw.sayHi("孙悟空"));
StringCat cCat=hw.getAllCats();
for (Entry entry: cCat.getEntries()) {
System.out.println(entry.getKey()+entry.getValue().getName());
}
}
}
运行结果:
孙悟空,您好现在的时间是:Sun Jul 31 17:52:52 CST 2016
第4个毛球
第3个花花
第1个丁丁
第2个咪咪
注:不是顺序的原因是,hashMap是通过Hash值排序的而不是通过Key排序。
至此我们使用适配器,解决了所有CXF解决不了的数据结构类型。
转载请注明出处:http://blog.csdn.net/acmman/article/details/52203040
转载请注明原文地址: https://ju.6miu.com/read-1296240.html