博主个人教程地址
前言 【Web|WebService开发 - CXF(4) - 服务端返回Map类型数据】之前说完了JavaBean的传递 今天来说一下Map类型的传递
Map类型传递 其实主要的还是针对的服务端的类型转换 所以主要修改的代码时在服务端的 我们还是按照正常的思路在扩充方法 来看一下会出现什么错误吧
还是在我们的接口中新增一个方法 返回一个Map类型的结构
代码如下
/* 获取所有用户角色 */
Map,List> getAllUserRole();
然后在实现类实现对应的方法
@Override
public Map, List> getAllUserRole() {
// 声明Map存储用户角色信息
Map,List> myMap = new HashMap<>();
// 创建第一个用户角色列表
List list1 = new ArrayList<>();
list1.add(new Role(1,"root"));
list1.add(new Role(1,"guest"));
myMap.put("lwx",list1);
// 创建第二个用户角色列表
List list2 = new ArrayList<>();
list1.add(new Role(1,"guest"));
myMap.put("jack",list2);
return myMap;
}
然后呢 我们还是 开心的去发布我们的服务端代码
会发现报如下错误
Exception in thread "main" org.apache.cxf.service.factory.ServiceConstructionException
at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:354)
at org.apache.cxf.service.factory.AbstractServiceFactoryBean.initializeDataBindings(AbstractServiceFactoryBean.java:86)
at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:469)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:693)
at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:529)
at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:262)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:199)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:103)
at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:168)
at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:211)
at top.liwenxiang.server.main.main.main(main.java:20)
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.util.List是接口, 而 JAXB 无法处理接口。
this problem is related to the following location:
at java.util.List
at private java.util.Map top.liwenxiang.server.service.jaxws_asm.GetAllUserRoleResponse._return
at top.liwenxiang.server.service.jaxws_asm.GetAllUserRoleResponse at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:76)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:441)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.(JAXBContextImpl.java:273)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.(JAXBContextImpl.java:109)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1126)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:135)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:441)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at org.apache.cxf.common.jaxb.JAXBContextCache$2.run(JAXBContextCache.java:345)
at org.apache.cxf.common.jaxb.JAXBContextCache$2.run(JAXBContextCache.java:343)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.common.jaxb.JAXBContextCache.createContext(JAXBContextCache.java:343)
at org.apache.cxf.common.jaxb.JAXBContextCache.getCachedContextAndSchemas(JAXBContextCache.java:245)
at org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContextAndSchemas(JAXBDataBinding.java:497)
at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:352)
... 10 more
这个错误就是不能够识别我们接口对应方法的返回类型 而抛出的错误信息 我们需要解决 并且让cxf能够识别这个类型 所以我们需要进行一个适配的操作
首先我们在我们对应返回map的方法上面加上一个注解 @XmlJavaTypeAdapter(MyMapAdapter.class)
MyMapAdapter 这个类使我们一会自己需要新建的
/* 获取所有用户角色 */
@XmlJavaTypeAdapter(MyMapAdapter.class)
Map,List> getAllUserRole();
新建MyMapAdapter类并继承XmlAdapter类 实现其中的方法 并编写对应代码 进行转换
XmlAdapter
实现两个方法 进行相互转换 一个是 从 Map 转换到 MyRole 一个是从MyRole转换到Map
我们的MyRole是需要进行创建的 借助这么一个中间实体类进行值得设置
- MyRole 代码
package top.liwenxiang.server.entity;
import java.util.List;
public class MyRole {private String key;
private List value;
public String getKey() {
return key;
}public void setKey(String key) {
this.key = key;
}public List getValue() {
return value;
}public void setValue(List value) {
this.value = https://www.it610.com/article/value;
}
}
- MyMapAdapter 代码
package top.liwenxiang.server.adapter;
import top.liwenxiang.server.entity.MyRole;
import top.liwenxiang.server.entity.Role;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyMapAdapter extends XmlAdapter>> {/**
* Convert a value type to a bound type.
*
* @param v The value to be converted. Can be null.
* @throws Exception if there's an error during the conversion. The caller is responsible for
*reporting the error to the user through {@link ValidationEventHandler}.
*//* 这里通过遍历得到Map并返回 */
@Override
public Map, List> unmarshal(MyRole[] v) throws Exception {
Map, List> map = new HashMap<>();
for (int i = 0 ;
i < v.length ;
i++){
map.put(v[i].getKey(),v[i].getValue());
}
return map;
}/**
* Convert a bound type to a value type.
*
* @param v The value to be convereted. Can be null.
* @throws Exception if there's an error during the conversion. The caller is responsible for
*reporting the error to the user through {@link ValidationEventHandler}.
*/
/* 通过遍历得到MyRole数组并返回 */
@Override
public MyRole[] marshal(Map, List> v) throws Exception {
MyRole[] roles = new MyRole[v.size()];
int i = 0;
for(String key : v.keySet()){
MyRole m = new MyRole();
roles[i] = m;
roles[i].setKey(key);
roles[i].setValue(v.get(key));
i++;
}
return roles;
}
}
编写完毕之后呢 再次去发布咱们的服务端服务就成功了
接下来还是去生成咱们的客户端代码 和之前一样
执行对应命令
文章图片
生成完毕之后编写客户端代码 对应的类都会生成出来
文章图片
客户端代码
通过getItem方法就可以得到一个List集合 返回我们的MyRole实体 在里面遍历可以获取到对应的用户名称和角色
package client;
import top.liwenxiang.server.service.*;
import java.io.UnsupportedEncodingException;
import java.util.List;
public class invoke {
public static void main(String[] args) throws UnsupportedEncodingException, UnsupportedEncodingException_Exception {
HelloWebServiceService helloWebServiceService = new HelloWebServiceService();
HelloWebService helloWebServicePort = helloWebServiceService.getHelloWebServicePort();
MyRoleArray allUserRole = helloWebServicePort.getAllUserRole();
List item = allUserRole.getItem();
System.out.println(item);
}
}
输出结果
[top.liwenxiang.server.service.MyRole@6a6824be, top.liwenxiang.server.service.MyRole@5c8da962]
结语 本篇主要是针对服务端的改进 以使其能够支持Map类型的返回~ 记得自己动手编写一下哦 ~
推荐阅读
- JavaScript|JavaScript: BOM对象 和 DOM 对象的增删改查
- web前端笔记|web前端学习-第一天
- JAVA框架之路|spring-boot笔记-工程搭建(一)
- spring|Java学习笔记(SpringMVC)
- URL协议和HTTP协议
- Web服务器的环境