传递、返回复杂类型的对象(axis服务端/axis客户端)

5 篇文章 0 订阅

转:http://www.cnblogs.com/hoojo/archive/2010/12/20/1911380.html

上面的服务传递的是简单数据类型,返回的也是简单数据类型。下面我们用JavaBean 、List、Map、Array等返回值或参数完成WebService。

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

 

复制代码
   
   
package com.hoo.entity; import java.io.Serializable; /** * <b>function:</b>User Entity * @author hoojo * @createDate Dec 16, 2010 10:20:02 PM * @file User.java * @package com.hoo.entity * @project AxisWebService * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class User implements Serializable { private static final long serialVersionUID = 677484458789332877L ; private int id; private String name; private String email; private String address; // Constractor // getter、setter @Override public String toString() { return this .id + " # " + this .name + " # " + this .email + " # " + this .address; } }
复制代码

 

 

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

 

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

 

复制代码
   
   
package com.hoo.service; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import com.hoo.entity.User; /** * <b>function:</b>axis WebService传递复杂类型数据 * @author hoojo * @createDate Dec 16, 2010 10:21:06 PM * @file ManagerUser.java * @package com.hoo.service * @project AxisWebService * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @SuppressWarnings( " deprecation " ) public class ManagerUser { public User getUserByName(String name) { User user = new User(); user.setId( new Date().getSeconds()); user.setName(name); user.setAddress( " china " ); user.setEmail(name + " @hoo.com " ); return user; } public void setUser(User user) { System.out.println(user); } public List < User > getUsers( int i) { List < User > users = new ArrayList < User > (); for ( int j = 0 ; j <= i; j ++ ) { User user = new User(); user.setId( new Date().getSeconds()); user.setName( " jack# " + j); user.setAddress( " china " ); user.setEmail( " jack " + j + " @hoo.com " ); users.add(user); } return users; } public void setUserMap(Map < String, User > maps) { System.out.println(maps); } public User[] getUserArray( int i) { User[] users = new User[i]; for ( int j = 0 ; j < i; j ++ ) { User user = new User(); user.setId( new Date().getSeconds()); user.setName( " jack# " + j); user.setAddress( " china " ); user.setEmail( " jack " + j + " @hoo.com " ); users[j] = user; } return users; } public void setUserArray(User[] users) { for (User u : users) { System.out.println(u); } } public Map < String, User > getUserMap() { Map < String, User > users = new HashMap < String, User > (); User user = new User(); user.setId( new Date().getSeconds()); user.setName( " jack# " ); user.setAddress( " china " ); user.setEmail( " jack@hoo.com " ); users.put( " A " , user); user = new User(); user.setId( new Date().getSeconds()); user.setName( " tom " ); user.setAddress( " china " ); user.setEmail( " tom@hoo.com " ); users.put( " B " , user); return users; } public void setUsers(List < User > users) { for (User u : users) { System.out.println(u); } } }
复制代码

 

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

 

复制代码
   
   
<? xml version="1.0" encoding="UTF-8" ?> < deployment xmlns ="http://xml.apache.org/axis/wsdd/" xmlns:java ="http://xml.apache.org/axis/wsdd/providers/java" > < service name ="ManagerUser" provider ="java:RPC" > < parameter name ="className" value ="com.hoo.service.ManagerUser" /> < parameter name ="allowedMethods" value ="*" /> < parameter name ="scope" value ="request" /> <!-- 这里的urn:User和new QName("urn:User", "User")这里是对应的 --> < beanMapping qname ="myNSD:User" xmlns:myNSD ="urn:User" languageSpecificType ="java:com.hoo.entity.User" /> </ service > </ deployment >
复制代码

 

 

 

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

 

复制代码
   
   
package com.hoo.client; import java.rmi.RemoteException; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.rpc.ParameterMode; import javax.xml.rpc.ServiceException; import org.apache.axis.client.Call; import org.apache.axis.client.Service; import org.apache.axis.encoding.XMLType; import org.apache.axis.encoding.ser.BeanDeserializerFactory; import org.apache.axis.encoding.ser.BeanSerializerFactory; import com.hoo.entity.User; /** * <b>function:</b>axis WebService传递复杂对象,客户端 * @author hoojo * @createDate Dec 16, 2010 10:32:57 PM * @file UserServiceClient.java * @package com.hoo.client * @project AxisWebService * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @SuppressWarnings( " unchecked " ) public class UserServiceClient { private static final String url = " http://localhost:8080/AxisWebService/services/ManagerUser " ; private static Service service = new Service(); public static User getUser(String name) throws ServiceException, RemoteException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); QName qn = new QName( " urn:User " , " User " ); // call.registerTypeMapping(User.class, qn, new BeanSerializerFactory(User.class, qn), new BeanDeserializerFactory(User.class, qn)); call.registerTypeMapping(User. class , qn, BeanSerializerFactory. class , BeanDeserializerFactory. class ); call.setOperationName( " getUserByName " ); /* * 这里客户端和服务器端共用一个User,在实际开发中 * 客户端和服务器端在不同的机器上,所以User对象可能不一样 * 需要我们根据WebService的wsdl分析对象的属性 */ call.addParameter( " name " , XMLType.XSD_STRING, ParameterMode.IN); call.setReturnClass(User. class ); User user = (User) call.invoke( new Object[] { " jackson " }); return user; } public static void setUser(User user) throws ServiceException, RemoteException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " setUser " ); // 设置参数类型 call.addParameter( " user " , qn, ParameterMode.IN); call.invoke( new Object[] { user }); } public static List < User > getUsers( int i) throws ServiceException, RemoteException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " getUsers " ); call.addParameter( " i " , XMLType.XSD_INT, ParameterMode.IN); call.setReturnClass(List. class ); List < User > users = (List < User > ) call.invoke( new Object[] { i }); return users; } public static void setUsers(List < User > users) throws ServiceException, RemoteException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " setUsers " ); call.addParameter( " users " , XMLType.XSD_ANYTYPE, ParameterMode.IN); call.invoke( new Object[] { users }); } public static void setUserMap(Map < String, User > maps) throws ServiceException, RemoteException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " setUserMap " ); call.addParameter( " maps " , XMLType.XSD_ANYTYPE, ParameterMode.IN); call.invoke( new Object[] { maps }); } public static Map < String, User > getUserMap() throws RemoteException, ServiceException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " getUserMap " ); // call.addParameter("null", XMLType.XSD_ANYTYPE, ParameterMode.IN); call.setReturnClass(Map. class ); Map < String, User > maps = (Map < String, User > ) call.invoke( new Object[]{}); return maps; } public static User[] getUserArray( int i) throws ServiceException, RemoteException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " getUserArray " ); call.addParameter( " i " , XMLType.XSD_INT, ParameterMode.IN); call.setReturnClass(User[]. class ); User[] users = (User[]) call.invoke( new Object[] { i }); return users; } public static void setUserArray(User[] users) throws RemoteException, ServiceException { Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); // 这里的QName的ns和wsdd文件中的对应 QName qn = new QName( " urn:User " , " User " ); // 这里是将对象序列化和反序列化的配置 call.registerTypeMapping(User. class , qn, new BeanSerializerFactory(User. class , qn), new BeanDeserializerFactory(User. class , qn)); call.setOperationName( " setUserArray " ); call.addParameter( " users " , XMLType.XSD_ANYTYPE, ParameterMode.IN); call.invoke( new Object[] { users }); } @SuppressWarnings( " deprecation " ) public static void main(String[] args) throws RemoteException, ServiceException { User user = new User(); user.setId( new Date().getSeconds()); user.setName( " tom " ); user.setAddress( " china " ); user.setEmail( " tom@hoo.com " ); System.out.println( " ============getUser============= " ); System.out.println(getUser( " jack " )); System.out.println( " ============setUser============= " ); setUser(user); // 看服务器端控制台 System.out.println( " ============getUsers List============= " ); List < User > users = getUsers( 3 ); for (User u : users) { System.out.println(u); } System.out.println( " ============setUsers List============= " ); setUsers(users); System.out.println( " ============getUserMap============= " ); Map < String, User > map = getUserMap(); System.out.println(map); System.out.println( " ============setUserMap============= " ); setUserMap(map); System.out.println( " ============getUserArray============= " ); User[] arr = getUserArray( 3 ); System.out.println( " ============setUserArray============= " ); setUserArray(arr); } }
复制代码

 

 

需要说明的是,这里传递的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是一个内部类,

 

复制代码
   
   
package com.hoo.entity; import java.io.Serializable; /** * <b>function:</b>Account Entity * @author hoojo * @createDate Dec 16, 2010 10:18:20 PM * @file Account.java * @package com.hoo.entity * @project AxisWebService * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class Account { private int id; private String name; private String email; private String address; private Birthday birthday; public Birthday getBrithday() { return birthday; } public void setBrithday(Birthday birthday) { this .birthday = birthday; } // getter、setter @Override public String toString() { return this .id + " # " + this .name + " # " + this .email + " # " + this .address + " # " + this .birthday.getBirthday(); } /** * axis中传的的内部类一定要是静态的,且要序列化 */ public static class Birthday implements Serializable { private static final long serialVersionUID = 1L ; private String bitthday; // getter、setter } }
复制代码

 

 

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

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是内部类的表示方式


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值