上面的服务传递的是简单数据类型,返回的也是简单数据类型。下面我们用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是内部类的表示方式

六、传递、返回复杂类型的对象相关推荐

  1. java 返回类对象_JAVA如何实现返回不同类型的对象

    JAVA如何实现返回不同类型的对象 发布时间:2020-11-10 16:11:51 来源:亿速云 阅读:96 作者:Leah 这篇文章运用简单易懂的例子给大家介绍JAVA如何实现返回不同类型的对象, ...

  2. java map转json字符串_Java-Gso-json字符串解析-php后台返回字段类型可能为字符串(/空字符串)或者对象的情况...

    其实本来android前端定义的对象类型是对象,如果后台没有值的情况下,理论上给null,如果是数组给[]或者null都可以的.这样Gson再解析转换的时候就不会出问题!但是最近重构发现后台如果没有字 ...

  3. ASP.NET MVC – 关于Action返回结果类型的事儿(上)

    本文转自:博客园-文超的技术博客 一.         ASP.NET MVC 1.0 Result 几何? Action的返回值类型到底有几个?咱们来数数看. ASP.NET MVC 1.0 目前一 ...

  4. (转)C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    原文链接:https://www.cnblogs.com/landeanfen/p/5501487.html 阅读目录 一.void无返回值 二.IHttpActionResult 1.Json(T ...

  5. 9.Java面向对象-方法参数类型及返回值类型、权限修饰符、内部类、匿名内部类

    9.Java面向对象-方法参数类型及返回值类型.权限修饰符.内部类.匿名内部类 一.类名作为形式参数 A:案例演示: 类名作为形式参数当你以后看到一个方法的形参要一个 类 类型,你就传递一个该类的对象 ...

  6. 【C++】day03 - 【类型与对象的概念】【类型】【构造函数】【一个对象创建的过程】【构造函数的应用】【头文件和实现文件的分离】【this指针】【析构函数】

    目录 一.类型与对象的概念 1.1什么是对象 1.2类型 二.如何在计算机中描述类型 2.1使用结构体(struct)对类型进行描述 2.2使用类(class)对类型进行描述 三.构造函数 3.1构造 ...

  7. Jquery ajax 返回string类型加result.d原因

    啥叫异步,啥叫Ajax.咱不谈啥XMLHTTPRequest.通俗讲异步就是前台页面javascript能调用后台方法.这样就达到了无刷新.所谓的Ajax.这里我们讲二种方法 方法一:(微软有自带Aj ...

  8. .net mvc actionresult 返回字符串_072-SpringMVC后端控制器接收参数、处理器方法返回值类型、拦截器、文件上传下载...

    1. 注解式开发之annotation-driven解释 (1) mvc注解驱动在哪个文件中配置? 在springmvc中配置 (2) 配置mvc注解驱动使用哪个标签? 2. 注解式开发之视图解析器 ...

  9. Winform中实现序列化指定类型的对象到指定的Xml文件和从指定的Xml文件中反序列化指定类型的对象

    场景 在Winform程序中需要将某些页面的设置存储到配置文件中,下次再次打开时通过配置文件读取,点击确定时能将将设置保存到配置文件中. 之前介绍过 Winform中自定义xml配置文件后对节点进行读 ...

最新文章

  1. phonegap 2.7 ios配置安装详细教程(2.9通用)
  2. spring用xml还是java_Spring中如何混用XML与Java装配方式
  3. ACM Fellow发文抨击「同行评审」作弊:有「门道」的作者带飞,垃圾论文也能轻松中顶会...
  4. Java后台开发Tomcat添加https支持小程序开发过程
  5. HDFS的JAVA客户端编写
  6. SylixOS 内存管理源代码分析--pageLib.c
  7. NYOJ题目915-+-字符串
  8. 实验八555定时器及其应用
  9. 台式计算机 按键盘字母键 没反应6,电脑键盘数字键失灵-键盘字母上面数字键有的失灵不能用怎么?键盘字母上面数字键有的失灵 爱问知识人...
  10. Android-Skin-Loader换肤框架剖析
  11. 解决Kangle的Easypanel控制面板用户前台php版本无法切换的解决方法
  12. 线性代数史蒂文_史蒂文·弗兰克的博客国歌
  13. ps磨皮滤镜插件Portraiture for Mac 破解方法
  14. 立方体图片的在线绘制与制作
  15. 如何抓包分析BLE 空口报文(GAP + GATT + LESC procedure)?
  16. ios使用js日期函数处理时的问题
  17. 开源的意义是什么?盘点当前五大优质开源项目
  18. 龙猫服务器注册,龙猫数据BPO,为企业打造安全专业的标注外包服务
  19. LabelImg 无法保存修改后的xml文件
  20. GetDocument()

热门文章

  1. 在Android 6.0 Marshmallow(API 23)上弃用了getColor(int id)
  2. 如何在延迟后触发一个块,比如-performSelector:withObject:afterDelay:?
  3. redis的安装和命令的使用(史上最全命令集合)
  4. 使用windows 10 安装中文版语言
  5. python36.dll下载_python36.dll
  6. 去除maven父依赖_如何在Maven中从父项目中排除依赖项?
  7. 洛谷——P1830 轰炸III
  8. Eigen教程(9)之Reshape,Slicing介绍
  9. Create React App 2.0 正式发布:Babel 7、webpack 4 等
  10. 通过字符串方法创建新字符串如何打出反斜杠、单引号、双引号、响铃、换行符、水平制表符