webService怎么返回map类型

CXF形参、返回值
1. 当形参和返回值的类型是String、基本数据类型是,CXF肯定可以轻松处理
2.当形参和返回值的类型是javabean式的复合类(就是普通的POJO实体类)、List集合、数组等复杂类型时, CXF也可以很好处理。
3.还有一些像Map、非javabean式的复合类,CXF是处理不了的
如果遇到系统无法自动处理的类型,就需要程序员自行处理,方法是提供一个转化器,该转化器负责把CXF不能处理的类型,转化为CXF能够处理的类型,具体过程如下:
(1) 使用注解 @XmlJavaTypeAdapter(java自身的注解,可在jdkAPI文档中查到)修饰CXF无法自动处理的类型,使用该Annotation时,通过value属性指定一个转换器(自己定义)。
@XmlJavaTypeAdapter (value="https://www.it610.com/article/MyXmlAdapter.class")


(2) 实现自己定义的转化器,实现转化器时,需要开发一个CXF能够处理的类型。


1. 注解@XmlJavaTypeAdapter标识返回值为Map的接口

  1. @WebService
  2. public interface HelloWorld {
  3. @XmlJavaTypeAdapter((XmlMapAdapter.class)) Map getSpace(String deviceIp);
  4. }

实现类保持不变:
  1. @Component("hello")
  2. @WebService(endpointInterface = "demo.spring.service.HelloWorld")
  3. public class HelloWorldImpl implements HelloWorld {
  4. public Map getSpace(String deviceIp) {
  5. // TODO Auto-generated method stub
  6. HashMap test = new HashMap();
  7. test.put("test","10.5");
  8. test.put("ip", deviceIp);
  9. System.out.println("deviceIp: " + deviceIp);
  10. return test;
  11. }
  12. }

2.定义自行创建的XmlMapAdapter类型
  1. public class XmlMapAdapter extends XmlAdapter> {
  2. @Override
  3. public Map unmarshal(MyStringMap v) throws Exception {
  4. // TODO Auto-generated method stub
  5. Map result = new HashMap();
  6. for (Entry entry : v.getEntries()) {
  7. result.put(entry.getKey(), entry.getValue());
  8. }
  9. return result;
  10. }
  11. @Override
  12. public MyStringMap marshal(Map v) throws Exception {
  13. // TODO Auto-generated method stub
  14. MyStringMap msm = new MyStringMap();
  15. List eList = new ArrayList();
  16. for(String key : v.keySet()) {
  17. Entry entry = new Entry();
  18. entry.setKey(key);
  19. entry.setValue(v.get(key));
  20. eList.add(entry);
  21. }
  22. msm.setEntries(eList);
  23. return msm;
  24. }
  25. }

通过继承XmlAdapter类型,便可已将CXF不能处理的类型进行转换。
jdkAPI中定义如下,valuType是能够处理的类型,boundType是不能处理的类型:
转化的实质是将不能处理的类型,如Map,将其值取出,赋予另一个实体类,这个类模拟Map,保存他的值,这样便是可以进行相互转化。为此,需要定义一个Map的模拟类,这样Map的key和value都保存在Entry类中(Entry自行定义,名字也可以随便,只要符合命名规范就行),所有的Entry保存在List中,这样一个Map集合就转化成了MyStringMap类,MyStringMap自然也可以转化为Map类:
  1. public class MyStringMap {
  2. private List entries;
  3. /**
  4. * @return entries
  5. */
  6. public List getEntries() {
  7. return entries;
  8. }
  9. /**
  10. * @param entries the entries to set
  11. */
  12. public void setEntries(List entries) {
  13. this.entries = entries;
  14. }
  15. public static class Entry {
  16. private String key;
  17. private String value;
  18. /**
  19. * @return key
  20. */
  21. public String getKey() {
  22. return key;
  23. }
  24. /**
  25. * @param key the key to set
  26. */
  27. public void setKey(String key) {
  28. this.key = key;
  29. }
  30. /**
  31. * @return value
  32. */
  33. public String getValue() {
  34. return value;
  35. }
  36. /**
  37. * @param value the value to set
  38. */
  39. public void setValue(String value) {
  40. this.value = https://www.it610.com/article/value;
  41. }
  42. }
  43. }


3.部署项目到tomcat中,启动,如能访问到WSDL文件,WSDL发布成功。
4.使用命令生成客户端,具体方法见博文。
5.测试客户端:

  1. public static void main(String []args) {
  2. HelloWorldImplService service = new HelloWorldImplService();
  3. HelloWorld hw = service.getHelloWorldImplPort();
  4. MyStringMap msm = hw.getSpace("");
  5. List entries = msm.getEntries();
  6. for (Entry e : entries) {
  7. System.out.println("key: " + e.getKey() + " " + "value: " + e.getValue());
  8. }
  9. }

结果如下
  1. 2013-4-3 15:56:19 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
  2. 信息: Creating Service {http://service.spring.demo/}HelloWorldImplService from WSDL: http://192.168.1.133:8088/CXFUseCase/services/helloWorld?wsdl
  3. key: test value: 10.5
  4. key: ip value: 192.168.3.51

    推荐阅读