cxf处理java bean及List、Map类型
cxf处理java bean及List、Map类型
项目中经常是处理复合类型比如集合List、Map,下面就cxf处理复合类型进行讲解。
具体例子如下:
这里实例是客户端传一个JavaBean,服务器端返回集合类型;
一、 接口返回List处理:
在原来的项目实例(cxf开发webService服务端口)基础上,我们先创建一个实体类User:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.entity;
- 5
- 6 /**
- 7 * @ClassName: User
- 8 * @Description: 用户实体类
- 9 * @author jed
- 10 * @date 2017年7月30日下午2:44:41
- 11 *
- 12 */
- 13 public class User {
- 14
- 15 private Integer id; // 编号
- 16 private String userName; //用户名
- 17 private String password; //密码
- 18
- 19 public Integer getId() {
- 20 return id;
- 21 }
- 22 public void setId(Integer id) {
- 23 this.id = id;
- 24 }
- 25 public String getUserName() {
- 26 return userName;
- 27 }
- 28 public void setUserName(String userName) {
- 29 this.userName = userName;
- 30 }
- 31 public String getPassword() {
- 32 return password;
- 33 }
- 34 public void setPassword(String password) {
- 35 this.password = password;
- 36 }
- 37
- 38
- 39 }
View Code
再创建一个Role实体类:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.entity;
- 5
- 6 /**
- 7 * @ClassName: Role
- 8 * @Description: TODO
- 9 * @author jed
- 10 * @date 2017年7月30日下午2:46:45
- 11 *
- 12 */
- 13 public class Role {
- 14
- 15 private Integer id; //编号
- 16 private String roleName; //角色名称
- 17
- 18 public Role() {
- 19 super();
- 20 }
- 21
- 22 public Role(Integer id, String roleName) {
- 23 super();
- 24 this.id = id;
- 25 this.roleName = roleName;
- 26 }
- 27
- 28 public Integer getId() {
- 29 return id;
- 30 }
- 31 public void setId(Integer id) {
- 32 this.id = id;
- 33 }
- 34 public String getRoleName() {
- 35 return roleName;
- 36 }
- 37 public void setRoleName(String roleName) {
- 38 this.roleName = roleName;
- 39 }
- 40
- 41
- 42 }
View Code
然后HelloWorld再加一个接口方法getRoleByUser,通过用户查找角色:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.webservice;
- 5
- 6 import java.util.List;
- 7
- 8 import javax.jws.WebService;
- 9
- 10 import com.hik.entity.Role;
- 11 import com.hik.entity.User;
- 12
- 13 /**
- 14 * @ClassName: HelloWorld
- 15 * @Description: TODO
- 16 * @author jed
- 17 * @date 2017年7月30日上午10:20:35
- 18 *
- 19 */
- 20 @WebService
- 21 public interface HelloWorld {
- 22
- 23 public String say(String str);
- 24
- 25 public List<Role> getRoleByUser(User user);
- 26 }
View Code
然后HelloWorld接口实现类 HelloWorldImpl写下新增的方法的具体实现,我们这里写死,模拟下即可:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.webservice.impl;
- 5
- 6 import java.util.ArrayList;
- 7 import java.util.List;
- 8
- 9 import javax.jws.WebService;
- 10
- 11 import com.hik.entity.Role;
- 12 import com.hik.entity.User;
- 13 import com.hik.webservice.HelloWorld;
- 14
- 15 /**
- 16 * @ClassName: HelloWorldImpl
- 17 * @Description: TODO
- 18 * @author jed
- 19 * @date 2017年7月30日上午10:24:46
- 20 *
- 21 */
- 22 @WebService
- 23 public class HelloWorldImpl implements HelloWorld{
- 24
- 25 public String say(String str) {
- 26 return "hello "+str;
- 27 }
- 28
- 29 public List<Role> getRoleByUser(User user) {
- 30 List<Role> roleList = new ArrayList<Role>();
- 31 if(user!=null){
- 32 if(user.getUserName().equals("jack") && user.getPassword().equals("123456")){
- 33 roleList.add(new Role(1, "技术总监"));
- 34 roleList.add(new Role(2, "产品经理"));
- 35 }else if(user.getUserName().equals("lili") && user.getPassword().equals("123456")){
- 36 roleList.add(new Role(3, "程序员"));
- 37 }
- 38 return roleList;
- 39 }else{
- 40 return null;
- 41 }
- 42
- 43 }
- 44
- 45 }
View Code
服务端其他地方不用动;再重新发布下webService接口。
下面我们来处理下客户端,和前面讲的一样。我们用wsdl2java工具重新生成代码(参考cxf开发webService客户端及调用服务端的理解 )
我们改下Client类:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.webservice;
- 5
- 6 import java.util.List;
- 7
- 8 /**
- 9 * @ClassName: Client
- 10 * @Description: TODO
- 11 * @author jed
- 12 * @date 2017年7月30日下午1:58:36
- 13 *
- 14 */
- 15 public class Client {
- 16
- 17 public static void main(String[] args) {
- 18 HelloWorldService service = new HelloWorldService();
- 19 HelloWorld helloWorld = service.getHelloWorldPort(); //代理
- 20 //System.out.println(helloWorld.say("你好!"));
- 21 User user = new User();
- 22 user.setUserName("lili");
- 23 user.setPassword("123456");
- 24 List<Role> roleList = helloWorld.getRoleByUser(user);
- 25 for(Role role : roleList){
- 26 System.out.println(role.getId()+" , "+role.getRoleName());
- 27 }
- 28 }
- 29 }
View Code
运行截图:
二、接口返回Map处理
map类型比较特殊,由其数据结构而决定。XmlAdapter类源码也有说明:
因此,需要写一个适配器来做转换,使用注解annotation注解 。该适配器类需实现抽象类XmlAdapter的两个转换方法。
代码例子如下:
如增加接口:获取所有用用户以及对应的每个用户所有角色信息;
服务器端:
HelloWorld接口加方法:
- 1 /**
- 2 *
- 3 * @MethodName: getRoles
- 4 * @Description: 获取所有用户及对应角色
- 5 * @author jed
- 6 * @date 2017年8月4日下午10:36:59
- 7 * @param @return
- 8 * @return Map<String,List<Role>> 返回类型
- 9 * @return
- 10 *
- 11 */
- 12 @XmlJavaTypeAdapter(MapAdapter.class)
- 13 public Map<String, List<Role>> getRoles();
View Code
HelloWorldImpl实现类加方法实现:
- 1 public Map<String, List<Role>> getRoles() {
- 2 Map<String, List<Role>> map = new HashMap<String, List<Role>>();
- 3 List<Role> roleList1 = new ArrayList<Role>();
- 4 roleList1.add(new Role(1, "技术总监"));
- 5 roleList1.add(new Role(2, "产品经理"));
- 6 map.put("admin", roleList1);
- 7 List<Role> roleList2 = new ArrayList<Role>();
- 8 roleList2.add(new Role(3, "程序员"));
- 9 map.put("jack", roleList2);
- 10 return map;
- 11 }
View Code
然后我们启动Server类:发现报错:
报错显示不支持该类型,解决方案,可以使用适配器,把cxf不能接受的类型通过适配器,转能接受的类型。
我们使用@XmlJavaTypeAdapter注解,加在接口定义上,完整接口代码如下:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.webservice;
- 5
- 6 import java.util.List;
- 7 import java.util.Map;
- 8
- 9 import javax.jws.WebService;
- 10 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
- 11
- 12 import com.hik.adapter.MapAdapter;
- 13 import com.hik.entity.Role;
- 14 import com.hik.entity.User;
- 15
- 16 /**
- 17 * @ClassName: HelloWorld
- 18 * @Description: TODO
- 19 * @author jed
- 20 * @date 2017年7月30日上午10:20:35
- 21 *
- 22 */
- 23 @WebService
- 24 public interface HelloWorld {
- 25
- 26 public String say(String str);
- 27
- 28 /**
- 29 *
- 30 * @MethodName: getRoleByUser
- 31 * @Description: 获取用户角色
- 32 * @author jed
- 33 * @date 2017年8月4日下午10:37:30
- 34 * @param @param user
- 35 * @param @return
- 36 * @return List<Role> 返回类型
- 37 * @param user
- 38 * @return
- 39 *
- 40 */
- 41 public List<Role> getRoleByUser(User user);
- 42
- 43 /**
- 44 *
- 45 * @MethodName: getRoles
- 46 * @Description: 获取所有用户及对应角色
- 47 * @author jed
- 48 * @date 2017年8月4日下午10:36:59
- 49 * @param @return
- 50 * @return Map<String,List<Role>> 返回类型
- 51 * @return
- 52 *
- 53 */
- 54 @XmlJavaTypeAdapter(MapAdapter.class)
- 55 public Map<String, List<Role>> getRoles();
- 56 }
View Code
这里参数需要一个实现了XmlAdapter类的适配器类;
这里的话XmlAdapter要加两个参数,XmlAdapter<ValueType,BoundType>
ValueType是cxf能接收的类型,这里我用了数组;
BoundType是cxf不能接受的类型,也就是我例子里的需求的Map类型;
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.adapter;
- 5
- 6 import java.util.HashMap;
- 7 import java.util.List;
- 8 import java.util.Map;
- 9
- 10 import javax.xml.bind.annotation.adapters.XmlAdapter;
- 11
- 12 import com.hik.entity.Role;
- 13
- 14 /**
- 15 * @ClassName: MapAdapter
- 16 * @Description: Map适配器
- 17 * @author jed
- 18 * @date 2017年8月4日下午10:56:41
- 19 *
- 20 */
- 21 public class MapAdapter extends XmlAdapter<MyRole[], Map<String, List<Role>>>{
- 22
- 23 /**
- 24 * 适配转换 MyRole[] -> Map<String, List<Role>>
- 25 */
- 26 @Override
- 27 public Map<String, List<Role>> unmarshal(MyRole[] v) throws Exception {
- 28 Map<String, List<Role>> map = new HashMap<String, List<Role>>();
- 29 for(int i=0;i<v.length;i++){
- 30 MyRole r = v[i];
- 31 map.put(r.getKey(), r.getValue());
- 32 }
- 33 return map;
- 34 }
- 35
- 36 /**
- 37 * 适配转换 Map<String, List<Role>> -> MyRole[]
- 38 */
- 39 @Override
- 40 public MyRole[] marshal(Map<String, List<Role>> v) throws Exception {
- 41 MyRole[] roles = new MyRole[v.size()];
- 42 int i=0;
- 43 for(String key : v.keySet()){
- 44 roles[i] = new MyRole();
- 45 roles[i].setKey(key);
- 46 roles[i].setValue(v.get(key));
- 47 i++;
- 48 }
- 49
- 50 return roles;
- 51 }
- 52
- 53 }
View Code
还有一个MyRole自定义类型,key:value。我们搞成两个属性,具体实现如下:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.adapter;
- 5
- 6 import java.util.List;
- 7
- 8 import com.hik.entity.Role;
- 9
- 10 /**
- 11 * @ClassName: MyRole
- 12 * @Description: 自定义实体 cxf能接受
- 13 * @author jed
- 14 * @date 2017年8月4日下午11:01:23
- 15 *
- 16 */
- 17 public class MyRole {
- 18
- 19 private String key;
- 20 private List<Role> value;
- 21
- 22 public String getKey() {
- 23 return key;
- 24 }
- 25 public void setKey(String key) {
- 26 this.key = key;
- 27 }
- 28 public List<Role> getValue() {
- 29 return value;
- 30 }
- 31 public void setValue(List<Role> value) {
- 32 this.value = value;
- 33 }
- 34
- 35
- 36 }
View Code
OK 好了。我们运行Server类,发布webservice接口:
发布成功。然后就到了webservice客户端,我们用wsdl2java工具生成下最新代码
我们修改下Client类:
- 1 /**
- 2 *
- 3 */
- 4 package com.hik.webservice;
- 5
- 6 import java.util.List;
- 7
- 8 /**
- 9 * @ClassName: Client
- 10 * @Description: TODO
- 11 * @author jed
- 12 * @date 2017年7月30日下午1:58:36
- 13 *
- 14 */
- 15 public class Client {
- 16
- 17 public static void main(String[] args) {
- 18 HelloWorldService service = new HelloWorldService();
- 19 HelloWorld helloWorld = service.getHelloWorldPort(); //代理
- 20 //System.out.println(helloWorld.say("你好!"));
- 21 /*User user = new User();
- 22 user.setUserName("lili");
- 23 user.setPassword("123456");
- 24 List<Role> roleList = helloWorld.getRoleByUser(user);
- 25 for(Role role : roleList){
- 26 System.out.println(role.getId()+" , "+role.getRoleName());
- 27 }*/
- 28 MyRoleArray array = helloWorld.getRoles();
- 29 List<MyRole> roleList = array.item;
- 30 for(int i=0;i<roleList.size();i++){
- 31 MyRole mr = roleList.get(i);
- 32 System.out.println(mr.key+":");
- 33 for(Role r: mr.getValue()){
- 34 System.out.println(r.getId()+","+r.getRoleName()+" ");
- 35 }
- 36 System.out.println();
- 37 }
- 38 }
- 39 }
View Code
运行结果:
总结: webService处理过程如下:
1、webservice服务器端开发webservice接口,然后发布webservice;
2、通过一个Url调用webservice接口,发布的url是 http://192.168.0.102/helloWorld,则我们请求的url就是 http://192.168.0.102/helloWorld?wsdl
3、请求成功,返回一大串xml标记。这一大串xml即使wsdl。 wsdl (Web Services Description Language) 也就是Web Service描述语言,描述服务器端定义的webservice接口的相关信息。
4、wsdl描述可看到发布的方法。如:wsdl:types就是定义了一些变量,wsdl:message相当于定义方法,wsdl:portType相当与调用与返回。
5、客户端通过这个url请求,获得wsdl规范的xml文档片段信息,需用到SOAP(Simple Object Access Protocol)即简单对象访问协议,我们通过这个协议,来实现客户端,服务器端消息交互,SOAP使用XML消息调用远程方法;
当然交互的媒介就是xml,具体交互内容根据wsdl文档描述来。