WebService(四)Axis2+POJO+wsdl2java复合类型

使用版本:

eclipse:eclipse-jee-kepler-R-win32.zip
JDK:jdk-7u25-windows-i586.exe j2sdk1.4.2_06.rar
Myeclipse:myeclipse-8.5.0-win32.exe
Tomcat:apache-tomcat-7.0.42-windows-x86.zip apache-tomcat-5.0.12.zip
Axis2:axis2-1.6.2-bin.zip axis2-1.6.2-war.zip axis2-eclipse-codegen-plugin-1.6.2.zip axis2-eclipse-service-plugin-1.6.2.zip
Axis1:axis-1.4.rar
WebLogic:oepe-indigo-installer-12.1.1.0.1.201203120349-12.1.1-win32.exe
Spring:spring-framework-3.1.1.RELEASE-with-docs.zip
Hibernate:hibernate-distribution-3.6.10.Final-dist.zip
Structs2;struts-2.3.15.1-all.zip
SVN:eclipse-svnplugin(subclipse site-1.6.2)
Oracle9i:Oracle 9i Disk1.iso Oracle 9i Disk2.iso Oracle 9i Disk3.iso

流程和WebService(三)Axis2+POJO+wsdl2java类似,只是参数数据类型为符合类型

在实际的应用中,不仅需要使用WebService来传递简单类型的数据,有时也需要传递更复杂的数据,这些数据可以被称为复合类型的数据。
数组与类(接口)是比较常用的复合类型。
在Axis2中可以直接使用将WebService方法的参数或返回值类型声明成数组或类(接口)。但要注意,在定义数组类型时只能使用一维数组,如果想传递多维数组,可以使用分隔符进行分隔,如下面的代码所示:  String[] strArray = new String[]{ “自行车,飞机,火箭”,”中国,美国,德国”, “超人,蜘蛛侠,钢铁侠” }      上面的代码可以看作是一个3*3的二维数组。
在传递类的对象实例时,除了直接将数组类型声明成相应的类或接口,也可以将对象实例进行序列化,也就是说,将一个对象实例转换成字节数组进行传递,然后接收方再进行反序列化,还原这个对象实例。

一、复合类型

1.1 编写和发布WebService

1.1.1 新建

新建JAVA PROJECT工程,编写类文件

Axis2中不需要进行任何的配置,就可以直接将一个简单的POJO发布成WebService。

按如下方式新建类ComplexTypeService和DataForm

//package com.service;

import java.io.FileOutputStream;

import com.data.DataForm;

public class ComplexTypeService {
	// 上传图像,imageByte参数表示上传图像文件的字节,
	// length参数表示图像文件的字节长度(该参数值可能小于imageByte的数组长度)
	public boolean uploadImageWithByte(byte[] imageByte, int length) {
		FileOutputStream fos = null;
		try {
			// 将上传的图像保存在D盘的test1.jpg文件中
			fos = new FileOutputStream("d:\\test1.jpg");
			// 开始写入图像文件的字节
			fos.write(imageByte, 0, length);
			fos.close();

		} catch (Exception e) {
			return false;
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (Exception e) {
				}
			}
		}
		return true;
	}

	// 返回一维字符串数组
	public String[] getArray() {
		String[] strArray = new String[] { "自行车", "飞机", "火箭" };
		return strArray;
	}

	// 返回二维字符串数组
	public String[] getMDArray() {
		String[] strArray = new String[] { "自行车,飞机,火箭", "中国,美国,德国",
				"超人,蜘蛛侠,钢铁侠" };
		return strArray;
	}

	// 返回DataForm类的对象实例
	public DataForm getDataForm() {
		return new DataForm();
	}

	// 将DataForm类的对象实例序列化,并返回序列化后的字节数组
	public byte[] getDataFormBytes() throws Exception {
		java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
		java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos);
		oos.writeObject(new DataForm());

		return baos.toByteArray();
	}
}
package com.data;

public class DataForm implements java.io.Serializable {
	private String name = "bill";
	private int age = 20;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}

1.1.2 编译

编译:javac data\*.java service\*.java

1.1.3 发布

由于本示例的WebService类使用了一个Java类(DataForm类),因此,在发布WebService之前,需要先将DataForm.class文件复制到<Tomcat安装目录>\webapps\axis2\WEB-INF\classes\com\data目录中,然后将ComplexTypeService.class文件复制到<Tomcat安装目录>\webapps\axis2\WEB-INF\pojo目录中,

在浏览器地址栏中输入如下的URL:http://localhost:8080/axis2/services/listServices(需要启动TOMCAT)

1.2 Java调用WS客户端

新建JAVA PROJECT工程,引入AXIS2 JAR包

编写类

package com.client;

import javax.xml.namespace.QName;
import org.apache.axis2.addressing.EndpointReference;

import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;

public class ComplexTypeRPCClient {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

		RPCServiceClient serviceClient = new RPCServiceClient();
		Options options = serviceClient.getOptions();
		EndpointReference targetEPR = new EndpointReference(
				"http://localhost:8080/axis2/services/ComplexTypeService");
		options.setTo(targetEPR);

		// 下面的代码调用uploadImageWithByte方法上传图像文件
		// ///////////////////////////////////////
		// 打开图像文件,确定图像文件的大小
		java.io.File file = new java.io.File("d:\\images.jpg");
		java.io.FileInputStream fis = new java.io.FileInputStream(
				"d:\\images.jpg");
		// 创建保存要上传的图像文件内容的字节数组
		byte[] buffer = new byte[(int) file.length()];
		// 将图像文件的内容读取buffer数组中
		int n = fis.read(buffer);
		System.out.println("文件长度:" + file.length());
		Object[] opAddEntryArgs = new Object[] { buffer, n };
		Class[] classes = new Class[] { Boolean.class };
		QName opAddEntry = new QName("http://ws.apache.org/axis2",
				"uploadImageWithByte");
		fis.close();
		// 开始上传图像文件,并输出uploadImageWithByte方法的返回传
		System.out.println(serviceClient.invokeBlocking(opAddEntry,
				opAddEntryArgs, classes)[0]);

		// ///////////////////////////////////////
		// 下面的代码调用了getArray方法,并返回一维String数组
		// ///////////////////////////////////////
		opAddEntry = new QName("http://ws.apache.org/axis2", "getArray");
		String[] strArray = (String[]) serviceClient.invokeBlocking(opAddEntry,
				new Object[] {}, new Class[] { String[].class })[0];
		for (String s : strArray)
			System.out.print(s + "  ");
		System.out.println();

		// ///////////////////////////////////////
		// 下面的代码调用了getMDArray方法,并返回一维String数组
		// ///////////////////////////////////////
		opAddEntry = new QName("http://ws.apache.org/axis2", "getMDArray");
		strArray = (String[]) serviceClient.invokeBlocking(opAddEntry,
				new Object[] {}, new Class[] { String[].class })[0];
		for (String s : strArray) {
			String[] array = s.split(",");
			for (String ss : array)
				System.out.print("<" + ss + "> ");
			System.out.println();
		}
		System.out.println();

		// ///////////////////////////////////////
		// 下面的代码调用了getDataForm方法,并返回DataForm对象实例
		// ///////////////////////////////////////
		opAddEntry = new QName("http://ws.apache.org/axis2", "getDataForm");
		com.data.DataForm df = (com.data.DataForm) serviceClient
				.invokeBlocking(opAddEntry, new Object[] {},
						new Class[] { com.data.DataForm.class })[0];
		System.out.println(df.getAge());

		// ///////////////////////////////////////
		// 下面的代码调用了getDataFormBytes方法,并返回字节数组,最后将返回的字节数组反序列化后,转换成DataForm对象实例
		// ///////////////////////////////////////
		opAddEntry = new QName("http://ws.apache.org/axis2", "getDataFormBytes");
		buffer = (byte[]) serviceClient.invokeBlocking(opAddEntry,
				new Object[] {}, new Class[] { byte[].class })[0];
		java.io.ObjectInputStream ois = new java.io.ObjectInputStream(
				new java.io.ByteArrayInputStream(buffer));
		df = (com.data.DataForm) ois.readObject();
		System.out.println(df.getName());

		// ////////////////////////////////////////
	}

}

运行:

log4j:WARN No appenders could be found for logger (org.apache.axis2.context.AbstractContext).
log4j:WARN Please initialize the log4j system properly.
文件长度:64403
true
自行车  飞机  火箭  
<自行车> <飞机> <火箭> 
<中国> <美国> <德国> 
<超人> <蜘蛛侠> <钢铁侠> 

20
bill

二、二进制文件传输

如果要传递二进制文件(如图像、音频文件等),可以使用byte[]作为数据类型进行传递,然后客户端使用RPC方式进行调用。这样做只是其中的一种方法,除此之外,在客户端还可以使用wsdl2java命令生成相应的stub类来调用WebService

WebService类中包含byte[]类型参数的方法在wsdl2java生成的stub类中对应的数据类型不再是byte[]类型,而是javax.activation.DataHandler。DataHandler类是专门用来映射WebService二进制类型的。

在WebService类中除了可以使用byte[]作为传输二进制的数据类型外,也可以使用 javax.activation.DataHandler作为数据类型。不管是使用byte[],还是使用javax.activation.DataHandler作为WebService方法的数据类型,使用wsdl2java命令生成的stub类中相应方法的类型都是 javax.activation.DataHandler。而象使用.net、delphi生成的stub类的相应方法类型都是byte[]。这是由于javax.activation.DataHandler类是Java特有的,对于其他语言和技术来说,并不认识javax.activation.DataHandler类,因此,也只有使用最原始的byte[]了。

2.1 服务端代码及services.xml

package com.service;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import javax.activation.DataHandler;

public class FileService {
	// 使用byte[]类型参数上传二进制文件
	public boolean uploadWithByte(byte[] file, String filename) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(filename);
			fos.write(file);
			fos.close();
		} catch (Exception e) {
			return false;
		} finally {
			if (fos != null) {

				try {
					fos.close();
				} catch (Exception e) {
				}
			}
		}
		return true;
	}

	private void writeInputStreamToFile(InputStream is, OutputStream os)
			throws Exception {
		int n = 0;
		byte[] buffer = new byte[8192];
		while ((n = is.read(buffer)) > 0) {
			os.write(buffer, 0, n);
		}
	}

	// 使用DataHandler类型参数上传文件
	public boolean uploadWithDataHandler(DataHandler file, String filename) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(filename);
			// 可通过DataHandler类的getInputStream方法读取上传数据
			writeInputStreamToFile(file.getInputStream(), fos);
			fos.close();
		} catch (Exception e) {
			return false;
		} finally {
			if (fos != null) {
				try {
					fos.close();
				}

				catch (Exception e) {
				}
			}
		}
		return true;
	}
}
<service name="fileService">     
	<description>         
		文件服务    
	</description>      
	<parameter name="ServiceClass">         
		com.service.FileService      
	</parameter>          
	<messageReceivers>          
		<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"             
			class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />     
	</messageReceivers> 
</service>

2.2 生成及发布*.aar文件

2.3 wsdl2java生成stub文件

2.4 客户端

package com.client;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;

import com.client.FileServiceStub.UploadWithByte;
import com.client.FileServiceStub.UploadWithDataHandler;

public class FileServiceClient {

	public static void main(String[] args) throws Exception {

		FileServiceStub stub = new FileServiceStub();

		DataHandler dh = new DataHandler(new FileDataSource("d:\\images.jpg"));

		UploadWithByte uwb = new UploadWithByte();
		uwb.setArgs0(dh);
		uwb.setArgs1("d:\\image1.jpg");
		System.out.println(stub.uploadWithByte(uwb).get_return());

		UploadWithDataHandler uwbh = new UploadWithDataHandler();
		uwbh.setArgs0(dh);
		uwbh.setArgs1("d:\\image2.jpg");
		System.out.println(stub.uploadWithDataHandler(uwbh).get_return());
	}

}
log4j:WARN No appenders could be found for logger (org.apache.axis2.description.AxisOperation).
log4j:WARN Please initialize the log4j system properly.
true
true

发表回复