使用版本:
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