传递、返回复杂类型的对象

来源:互联网 发布:小米电视3怎么样 知乎 编辑:程序博客网 时间:2024/05/18 22:56

1、首先看看JavaBean模式的参数和返回值的WebService,JavaBean代码如下:

  1. package com.hoo.entity;  
  2. import java.io.Serializable;  
  3. /** 
  4.  * <b>function:</b>User Entity 
  5.  * @author hoojo 
  6.  * @createDate Dec 16, 2010 10:20:02 PM 
  7.  * @file User.java 
  8.  * @package com.hoo.entity 
  9.  * @project AxisWebService 
  10.  * @blog http://blog.csdn.net/IBM_hoojo 
  11.  * @email hoojo_@126.com 
  12.  * @version 1.0 
  13.  */  
  14. public class User implements Serializable {  
  15.     private static final long serialVersionUID = 677484458789332877L;  
  16.     private int id;  
  17.     private String name;  
  18.     private String email;  
  19.     private String address;  
  20.     //Constractor  
  21.     //getter、setter  
  22.     @Override  
  23.     public String toString() {  
  24.         return this.id + "#" + this.name + "#" + this.email + "#" + this.address;  
  25.     }  
  26. }  

 

 

 

没有上面特别就是一个普通的Java对象,里面提供一些属性及getter、setter方法和toString方法(在显示数据的时候有用),值 得注意的是在远程调用的Java对象都需要实现Serializable接口,这样在网络中传递对象的时候就不会出现重复的JavaBean。用过或是了 解EJB、RMI的朋友应该知道这点。序列化后的对象可以用io进行序列化写入到文件中,也可以反序列化解析到对象中的数据。

 

2、好,回正题。下面编写WebService的服务器端代码。

 

复制代码
  1. package com.hoo.service;  
  2. import java.util.ArrayList;  
  3. import java.util.Date;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7. import com.hoo.entity.User;  
  8. /** 
  9.  * <b>function:</b>axis WebService传递复杂类型数据 
  10.  * @author hoojo 
  11.  * @createDate Dec 16, 2010 10:21:06 PM 
  12.  * @file ManagerUser.java 
  13.  * @package com.hoo.service 
  14.  * @project AxisWebService 
  15.  * @blog http://blog.csdn.net/IBM_hoojo 
  16.  * @email hoojo_@126.com 
  17.  * @version 1.0 
  18.  */  
  19. @SuppressWarnings("deprecation")  
  20. public class ManagerUser {  
  21.       
  22.     public User getUserByName(String name) {  
  23.         User user = new User();  
  24.         user.setId(new Date().getSeconds());  
  25.         user.setName(name);  
  26.         user.setAddress("china");  
  27.         user.setEmail(name + "@hoo.com");  
  28.         return user;  
  29.     }  
  30.       
  31.     public void setUser(User user) {  
  32.         System.out.println(user);  
  33.     }  
  34.       
  35.     public List<User> getUsers(int i) {  
  36.         List<User> users = new ArrayList<User>();  
  37.         for (int j = 0; j <= i; j++) {  
  38.             User user = new User();  
  39.             user.setId(new Date().getSeconds());  
  40.             user.setName("jack#" + j);  
  41.             user.setAddress("china");  
  42.             user.setEmail("jack" + j + "@hoo.com");  
  43.             users.add(user);  
  44.         }  
  45.         return users;  
  46.     }  
  47.       
  48.     public void setUserMap(Map<String, User> maps) {  
  49.         System.out.println(maps);  
  50.     }  
  51.       
  52.     public User[] getUserArray(int i) {  
  53.         User[] users = new User[i];  
  54.         for (int j = 0; j < i; j++) {  
  55.             User user = new User();  
  56.             user.setId(new Date().getSeconds());  
  57.             user.setName("jack#" + j);  
  58.             user.setAddress("china");  
  59.             user.setEmail("jack" + j + "@hoo.com");  
  60.             users[j] = user;  
  61.         }  
  62.         return users;  
  63.     }  
  64.       
  65.     public void setUserArray(User[] users) {  
  66.         for (User u : users) {  
  67.             System.out.println(u);  
  68.         }  
  69.     }  
  70.       
  71.     public Map<String, User> getUserMap() {  
  72.         Map<String, User> users = new HashMap<String, User>();  
  73.         User user = new User();  
  74.         user.setId(new Date().getSeconds());  
  75.         user.setName("jack#");  
  76.         user.setAddress("china");  
  77.         user.setEmail("jack@hoo.com");  
  78.         users.put("A", user);  
  79.           
  80.         user = new User();  
  81.         user.setId(new Date().getSeconds());  
  82.         user.setName("tom");  
  83.         user.setAddress("china");  
  84.         user.setEmail("tom@hoo.com");  
  85.         users.put("B", user);  
  86.         return users;  
  87.     }  
  88.       
  89.     public void setUsers(List<User> users) {  
  90.         for (User u : users) {  
  91.             System.out.println(u);  
  92.         }  
  93.     }  
  94. }  
复制代码

 

3、编写wsdd文本发布当前WebService,wsdd文件代码如下:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <deployment xmlns="http://xml.apache.org/axis/wsdd/"  
  3. xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">  
  4. <service name="ManagerUser" provider="java:RPC">  
  5. <parameter name="className" value="com.hoo.service.ManagerUser" />  
  6. <parameter name="allowedMethods" value="*" />  
  7. <parameter name="scope" value="request" />  
  8. <!-- 这里的urn:User和new QName("urn:User", "User")这里是对应的 -->  
  9. <beanMapping qname="myNSD:User" xmlns:myNSD="urn:User" languageSpecificType="java:com.hoo.entity.User"/>  
  10. </service>  
  11. </deployment>  
  12.    

 

和上面的wsdd文件不同的是,这里多了beanMapping的配置。Qname是xml中规范限定名称,由命名空间url、本地名称、前缀组 成,本地名称是必需的且qname是不可变的。后面的myNSD(namespace)是必需的,是通过前面的qname指定的,myNSD后面的 urn:User就和程序中的QName对应的第一个参数,第二个参数对应配置文件中的qname的myNSD冒号后面的值。 languageSpecificType是javaBean的类路径。

 

4、发布WebService,还是允许命令行:

java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient -lhttp://localhost:8080/AxisWebService/services/AdminService deployComplex.wsdd

发布后,在浏览器中请求:

http://localhost:8080/AxisWebService/servlet/AxisServlet

就可以看到发布的WebService和暴露的方法了。

 

5、客户端代码的编写,这次客户端和以前有些不一样。因为这里设置了参数和返回值都是复杂类型,而不是简单的类型了。代码如下:

 

  1. package com.hoo.client;  
  2. import java.rmi.RemoteException;  
  3. import java.util.Date;  
  4. import java.util.List;  
  5. import java.util.Map;  
  6. import javax.xml.namespace.QName;  
  7. import javax.xml.rpc.ParameterMode;  
  8. import javax.xml.rpc.ServiceException;  
  9. import org.apache.axis.client.Call;  
  10. import org.apache.axis.client.Service;  
  11. import org.apache.axis.encoding.XMLType;  
  12. import org.apache.axis.encoding.ser.BeanDeserializerFactory;  
  13. import org.apache.axis.encoding.ser.BeanSerializerFactory;  
  14. import com.hoo.entity.User;  
  15. /** 
  16.  * <b>function:</b>axis WebService传递复杂对象,客户端 
  17.  * @author hoojo 
  18.  * @createDate Dec 16, 2010 10:32:57 PM 
  19.  * @file UserServiceClient.java 
  20.  * @package com.hoo.client 
  21.  * @project AxisWebService 
  22.  * @blog http://blog.csdn.net/IBM_hoojo 
  23.  * @email hoojo_@126.com 
  24.  * @version 1.0 
  25.  */  
  26. @SuppressWarnings("unchecked")  
  27. public class UserServiceClient {  
  28.       
  29.     private static final String url = "http://localhost:8080/AxisWebService/services/ManagerUser";  
  30.     private static Service service = new Service();   
  31.       
  32.     public static User getUser(String name) throws ServiceException, RemoteException {  
  33.         Call call = (Call) service.createCall();  
  34.         call.setTargetEndpointAddress(url);  
  35.         QName qn = new QName("urn:User""User");  
  36.         //call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  37.         call.registerTypeMapping(User.class, qn, BeanSerializerFactory.class, BeanDeserializerFactory.class);  
  38.         call.setOperationName("getUserByName");  
  39.         /* 
  40.          * 这里客户端和服务器端共用一个User,在实际开发中 
  41.          * 客户端和服务器端在不同的机器上,所以User对象可能不一样 
  42.          * 需要我们根据WebService的wsdl分析对象的属性 
  43.          */  
  44.         call.addParameter("name", XMLType.XSD_STRING, ParameterMode.IN);  
  45.         call.setReturnClass(User.class);  
  46.         User user = (User) call.invoke(new Object[] { "jackson" });  
  47.         return user;  
  48.     }  
  49.       
  50.     public static void setUser(User user) throws ServiceException, RemoteException {  
  51.         Call call = (Call) service.createCall();  
  52.         call.setTargetEndpointAddress(url);  
  53.         //这里的QName的ns和wsdd文件中的对应  
  54.         QName qn = new QName("urn:User""User");  
  55.         //这里是将对象序列化和反序列化的配置  
  56.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  57.         call.setOperationName("setUser");  
  58.         //设置参数类型  
  59.         call.addParameter("user", qn, ParameterMode.IN);  
  60.         call.invoke(new Object[] { user });  
  61.     }  
  62.       
  63.     public static List<User> getUsers(int i) throws ServiceException, RemoteException {  
  64.         Call call = (Call) service.createCall();  
  65.         call.setTargetEndpointAddress(url);  
  66.         //这里的QName的ns和wsdd文件中的对应  
  67.         QName qn = new QName("urn:User""User");  
  68.         //这里是将对象序列化和反序列化的配置  
  69.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  70.         call.setOperationName("getUsers");  
  71.         call.addParameter("i", XMLType.XSD_INT, ParameterMode.IN);  
  72.         call.setReturnClass(List.class);  
  73.         List<User> users = (List<User>) call.invoke(new Object[] { i });  
  74.         return users;  
  75.     }  
  76.       
  77.     public static void setUsers(List<User> users) throws ServiceException, RemoteException {  
  78.         Call call = (Call) service.createCall();  
  79.         call.setTargetEndpointAddress(url);  
  80.         //这里的QName的ns和wsdd文件中的对应  
  81.         QName qn = new QName("urn:User""User");  
  82.         //这里是将对象序列化和反序列化的配置  
  83.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  84.         call.setOperationName("setUsers");  
  85.         call.addParameter("users", XMLType.XSD_ANYTYPE, ParameterMode.IN);  
  86.         call.invoke(new Object[] { users });  
  87.     }  
  88.       
  89.     public static void setUserMap(Map<String, User> maps) throws ServiceException, RemoteException {  
  90.         Call call = (Call) service.createCall();  
  91.         call.setTargetEndpointAddress(url);  
  92.         //这里的QName的ns和wsdd文件中的对应  
  93.         QName qn = new QName("urn:User""User");  
  94.         //这里是将对象序列化和反序列化的配置  
  95.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  96.         call.setOperationName("setUserMap");  
  97.         call.addParameter("maps", XMLType.XSD_ANYTYPE, ParameterMode.IN);  
  98.         call.invoke(new Object[] { maps });  
  99.     }  
  100.       
  101.     public static Map<String, User> getUserMap() throws RemoteException, ServiceException {  
  102.         Call call = (Call) service.createCall();  
  103.         call.setTargetEndpointAddress(url);  
  104.         //这里的QName的ns和wsdd文件中的对应  
  105.         QName qn = new QName("urn:User""User");  
  106.         //这里是将对象序列化和反序列化的配置  
  107.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  108.         call.setOperationName("getUserMap");  
  109.         //call.addParameter("null", XMLType.XSD_ANYTYPE, ParameterMode.IN);  
  110.         call.setReturnClass(Map.class);  
  111.         Map<String, User> maps = (Map<String, User>) call.invoke(new Object[]{});  
  112.         return maps;  
  113.     }  
  114.       
  115.     public static User[] getUserArray(int i) throws ServiceException, RemoteException {  
  116.         Call call = (Call) service.createCall();  
  117.         call.setTargetEndpointAddress(url);  
  118.         //这里的QName的ns和wsdd文件中的对应  
  119.         QName qn = new QName("urn:User""User");  
  120.         //这里是将对象序列化和反序列化的配置  
  121.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  122.         call.setOperationName("getUserArray");  
  123.         call.addParameter("i", XMLType.XSD_INT, ParameterMode.IN);  
  124.         call.setReturnClass(User[].class);  
  125.         User[] users = (User[]) call.invoke(new Object[] { i });  
  126.         return users;  
  127.     }  
  128.       
  129.     public static void setUserArray(User[] users) throws RemoteException, ServiceException {  
  130.         Call call = (Call) service.createCall();  
  131.         call.setTargetEndpointAddress(url);  
  132.         //这里的QName的ns和wsdd文件中的对应  
  133.         QName qn = new QName("urn:User""User");  
  134.         //这里是将对象序列化和反序列化的配置  
  135.         call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));  
  136.         call.setOperationName("setUserArray");  
  137.         call.addParameter("users", XMLType.XSD_ANYTYPE, ParameterMode.IN);  
  138.         call.invoke(new Object[] { users });  
  139.     }  
  140.       
  141.     @SuppressWarnings("deprecation")  
  142.     public static void main(String[] args) throws RemoteException, ServiceException {  
  143.         User user = new User();  
  144.         user.setId(new Date().getSeconds());  
  145.         user.setName("tom");  
  146.         user.setAddress("china");  
  147.         user.setEmail("tom@hoo.com");  
  148.         System.out.println("============getUser=============");  
  149.         System.out.println(getUser("jack"));  
  150.         System.out.println("============setUser=============");  
  151.         setUser(user);//看服务器端控制台  
  152.         System.out.println("============getUsers List=============");  
  153.         List<User> users = getUsers(3);  
  154.         for (User u : users) {  
  155.             System.out.println(u);  
  156.         }  
  157.         System.out.println("============setUsers List=============");  
  158.         setUsers(users);  
  159.         System.out.println("============getUserMap=============");  
  160.         Map<String, User> map = getUserMap();  
  161.         System.out.println(map);  
  162.         System.out.println("============setUserMap=============");  
  163.         setUserMap(map);  
  164.         System.out.println("============getUserArray=============");  
  165.         User[] arr = getUserArray(3);  
  166.         System.out.println("============setUserArray=============");  
  167.         setUserArray(arr);  
  168.     }  
  169. }  
 

 

 

需要说明的是,这里传递的User和服务器端的User是同一个对象,在实际开发中应该不是同一个对象的。如java调用.net的WebService,传递的对象应该不是同一个。需要我们自己根据wsdl文件中的描述创建JavaBean。注意的是对象一个要序列化。

new QName("urn:User", "User")这里的QName的urn:User和wsdd文件中的对应,参数User也是和wsdd文件中的qname="myNSD:User" 对应的

这里是将对象序列化和反序列化的配置

call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn));

User是Mapping的对象,也就是更加wsdl中参数描述创建的Java对象

call.addParameter("i", XMLType.XSD_INT, ParameterMode.IN);设置参数信息,ParameterMode.IN代表传递的参数,XMLType.XSD_INT,代表参数的类型,前面的i是参数名称

call.setReturnClass(User[].class);设置返回值的类型

特别说明:

A、 如果你调用的方法有返回值,一定要设置返回值的类型。call.setReturnClass

B、 如果你调用的方法有参数,一定要设置参数的类型call.addParameter

C、 记得添加wsdl4j.jar,序列化转换的时候需要用到,否则会出现找不到类型异常

 

运行后,效果如下:

客户端:

============getUser=============

41#jackson#jackson@hoo.com#china

============setUser=============

- No returnType was specified to the Call object!  You must call setReturnType() if you have called addParameter().

============getUsers List=============

41#jack#0#jack0@hoo.com#china

41#jack#1#jack1@hoo.com#china

41#jack#2#jack2@hoo.com#china

41#jack#3#jack3@hoo.com#china

============setUsers List=============

- No returnType was specified to the Call object!  You must call setReturnType() if you have called addParameter().

============getUserMap=============

{A=41#jack##jack@hoo.com#china, B=41#tom#tom@hoo.com#china}

============setUserMap=============

- No returnType was specified to the Call object!  You must call setReturnType() if you have called addParameter().

============getUserArray=============

============setUserArray=============

- No returnType was specified to the Call object!  You must call setReturnType() if you have called addParameter().

 

服务器端:

37#tom#tom@hoo.com#china

37#jack#0#jack0@hoo.com#china

37#jack#1#jack1@hoo.com#china

37#jack#2#jack2@hoo.com#china

37#jack#3#jack3@hoo.com#china

{A=37#jack##jack@hoo.com#china, B=37#tom#tom@hoo.com#china}

37#jack#0#jack0@hoo.com#china

37#jack#1#jack1@hoo.com#china

37#jack#2#jack2@hoo.com#china

 

Map、Array、List、JavaBean都可以顺利转换,不管是参数还是返回值。怎么样,很简单吧!

 

传递内部类  

如果你传递的JavaBean带有内部类,那么你的内部类需要是静态化的,且一样要序列化。为Account对象添加一个属性Birthday,Birthday是一个内部类,

 

  1. package com.hoo.entity;  
  2. import java.io.Serializable;  
  3. /** 
  4.  * <b>function:</b>Account Entity 
  5.  * @author hoojo 
  6.  * @createDate Dec 16, 2010 10:18:20 PM 
  7.  * @file Account.java 
  8.  * @package com.hoo.entity 
  9.  * @project AxisWebService 
  10.  * @blog http://blog.csdn.net/IBM_hoojo 
  11.  * @email hoojo_@126.com 
  12.  * @version 1.0 
  13.  */  
  14. public class Account {  
  15.     private int id;  
  16.     private String name;  
  17.     private String email;  
  18.     private String address;  
  19.     private Birthday birthday;  
  20.       
  21.     public Birthday getBrithday() {  
  22.         return birthday;  
  23.     }  
  24.     public void setBrithday(Birthday birthday) {  
  25.         this.birthday = birthday;  
  26.     }  
  27.       
  28.     //getter、setter  
  29.       
  30.     @Override  
  31.     public String toString() {  
  32.         return this.id + "#" + this.name + "#" + this.email + "#" + this.address + "#" + this.birthday.getBirthday();  
  33.     }  
  34.       
  35.     /** 
  36.      * axis中传的的内部类一定要是静态的,且要序列化 
  37.      */  
  38.     public static class Birthday implements Serializable {  
  39.         private static final long serialVersionUID = 1L;  
  40.         private String bitthday;  
  41. //        getter、setter  
  42.     }  
  43. }  
 

 

同样我们需要在客户端调用的时候,注册类型序列化和反序列化。

QName qn = new QName("urn:Account", "entity.Account");

call.registerTypeMapping(Account.class , qn, new BeanSerializerFactory(Account.class , qn), new BeanDeserializerFactory(Account.class , qn));

QName qn2 = new QName("urn:Birthday", "Account.Birthday");

call.registerTypeMapping(Birthday.class , qn2, new BeanSerializerFactory(Birthday.class , qn2), new BeanDeserializerFactory(Birthday.class , qn2));

而在wsdd文件中和刚才几乎一样

<beanMapping qname="myNSD:entity.Account" xmlns:myNSD="urn:Account" languageSpecificType="java:com.hoo.entity.Account"/>

<beanMapping qname="myNSD:Account.Birthday" xmlns:myNSD="urn:Birthday" languageSpecificType="java:com.hoo.entity.Account$Birthday"/>com.hoo. com.hoo.entity.Account$Birthday是内部类的表示方式