Apache CXF实战之三 Map类型绑定
在CXF中,如果Web Service返回类型是Map的时候,比如方法签名如下view plaincopyprint?
[*]@WebMethod
[*]@WebResult Map<String, User> getUserMap();
此时如果运行程序会得到类似下面的异常
view plaincopyprint?
[*]...
[*]Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
[*]java.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.GetUserMapResponse
[*]java.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
[*]...
如果把方法签名改为如下时
view plaincopyprint?
[*]@WebMethod
[*]@WebResult HashMap<String, User> getUserMap();
运行程序会发现返回的结果总是一个空的HashMap。
对于以上问题,此时需要对Map类型做一下数据绑定或者说转换,看下面详细例子
1. 首先是一个实体类
view plaincopyprint?
[*]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类型做转换的类和适配器类
view plaincopyprint?
[*]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注解部分
view plaincopyprint?
[*]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;
[*]
[*]@WebService
[*]public interface UserService {
[*]
[*] @WebMethod
[*] @WebResult List<User> getUserList();
[*]
[*] @WebMethod
[*] @XmlJavaTypeAdapter(MapAdapter.class)
[*] @WebResult Map<String, User> getUserMap();
[*]}
4. WebService接口实现类
view plaincopyprint?
[*]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. 最后是一个单元测试类
view plaincopyprint?
[*]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. 运行单元测试类验证上面的实现。
页:
[1]