分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
本文链接:http://blog.csdn.net/kongxx/article/details/7544640
Apache CXF实战之一 Hello World Web Service
Apache CXF实战之四 构建RESTful Web Service
Apache CXF实战之五 压缩Web Service数据
Apache CXF实战之六 创建安全的Web Service
Apache CXF实战之七 使用Web Service传输文件
在CXF中,如果Web Service返回类型是Map的时候,比如方法签名如下
@WebMethod @WebResult Map<String, User> getUserMap();
此时如果运行程序会得到类似下面的异常
...Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptionsjava.util.Map is an interface, and JAXB can't handle interfaces. this problem is related to the following location: at java.util.Map at private java.util.Map com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse._return at com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponsejava.util.Map does not have a no-arg default constructor. this problem is related to the following location: at java.util.Map at private java.util.Map com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse._return at com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102) at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:472) at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302) at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1136) at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154) at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at javax.xml.bind.ContextFinder.newInstance(Unknown Source) at javax.xml.bind.ContextFinder.newInstance(Unknown Source) at javax.xml.bind.ContextFinder.find(Unknown Source) at javax.xml.bind.JAXBContext.newInstance(Unknown Source) at org.apache.cxf.jaxb.JAXBDataBinding.createContext(JAXBDataBinding.java:560) at org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContextAndSchemas(JAXBDataBinding.java:500) at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:320) ... 25 more...
如果把方法签名改为如下时
@WebMethod @WebResult HashMap<String, User> getUserMap();
运行程序会发现返回的结果总是一个空的HashMap。
对于以上问题,此时需要对Map类型做一下数据绑定或者说转换,看下面详细例子
1. 首先是一个实体类
package com.googlecode.garbagecan.cxfstudy.type.sample2;public class User { private String id; private String name; private String password; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
2. 对Map类型做转换的类和适配器类
package com.googlecode.garbagecan.cxfstudy.type.sample2;import java.util.HashMap;import java.util.Map;import javax.xml.bind.annotation.adapters.XmlAdapter;public class MapAdapter extends XmlAdapter<MapConvertor, Map<String, Object>> { @Override public MapConvertor marshal(Map<String, Object> map) throws Exception { MapConvertor convertor = new MapConvertor(); for (Map.Entry<String, Object> entry : map.entrySet()) { MapConvertor.MapEntry e = new MapConvertor.MapEntry(entry); convertor.addEntry(e); } return convertor; } @Override public Map<String, Object> unmarshal(MapConvertor map) throws Exception { Map<String, Object> result = new HashMap<String, Object>(); for (MapConvertor.MapEntry e : map.getEntries()) { result.put(e.getKey(), e.getValue()); } return result; }}package com.googlecode.garbagecan.cxfstudy.type.sample2;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.XmlType;@XmlType(name = "MapConvertor")@XmlAccessorType(XmlAccessType.FIELD)public class MapConvertor { private List<MapEntry> entries = new ArrayList<MapEntry>(); public void addEntry(MapEntry entry) { entries.add(entry); } public List<MapEntry> getEntries() { return entries; } public static class MapEntry { private String key; private Object value; public MapEntry() { super(); } public MapEntry(Map.Entry<String, Object> entry) { super(); this.key = entry.getKey(); this.value = entry.getValue(); } public MapEntry(String key, Object value) { super(); this.key = key; this.value = value; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } }}
3. 下面是WebService接口类,注意其中的@XmlJavaTypeAdapter注解部分
package com.googlecode.garbagecan.cxfstudy.type.sample2;import java.util.List;import java.util.Map;import javax.jws.WebMethod;import javax.jws.WebResult;import javax.jws.WebService;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;@WebServicepublic interface UserService { @WebMethod @WebResult List<User> getUserList(); @WebMethod @XmlJavaTypeAdapter(MapAdapter.class) @WebResult Map<String, User> getUserMap();}
4. WebService接口实现类
package com.googlecode.garbagecan.cxfstudy.type.sample2;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;public class UserServiceImpl implements UserService { public List<User> getUserList() { List<User> userList = new ArrayList<User>(); for (int i = 0; i < 10; i++) { User user = new User(); user.setId("" + i); user.setName("user_" + i); user.setPassword("password_" + i); userList.add(user); } return userList; } public Map<String, User> getUserMap() { Map<String, User> userMap = new LinkedHashMap<String, User>(); for (int i = 0; i < 10; i++) { User user = new User(); user.setId("" + i); user.setName("user_" + i); user.setPassword("password_" + i); userMap.put(user.getId(), user); } return userMap; }}
5. 最后是一个单元测试类
package com.googlecode.garbagecan.cxfstudy.type.sample2;import java.util.List;import java.util.Map;import javax.xml.ws.Endpoint;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import org.junit.After;import org.junit.Assert;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;public class UserServiceTest { private static final String address = "http://localhost:9000/ws/type/sample2/userService"; private UserService userService; @BeforeClass public static void setUpBeforeClass() throws Exception { Endpoint.publish(address, new UserServiceImpl()); } @Before public void setUp() throws Exception { JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean(); factoryBean.setAddress(address); factoryBean.setServiceClass(UserService.class); Object obj = factoryBean.create(); userService = (UserService)obj; } @After public void tearDown() throws Exception { userService = null; } @Test public void testGetUserList() { Assert.assertNotNull(userService); List<User> users = userService.getUserList(); Assert.assertNotNull(users); Assert.assertEquals(10, users.size()); } @Test public void testGetUserMap() { Assert.assertNotNull(userService); Map<String, User> users = userService.getUserMap(); Assert.assertNotNull(users); Assert.assertEquals(10, users.size()); }}
6. 运行单元测试类验证上面的实现。