在實際應用中,不只須要使用WebService來傳遞簡單類型的數據,有時也須要傳遞更復雜的數據,這些數據能夠被稱爲複合類型的數據。數組與類(接口)是比較經常使用的複合類型。在Axis2中能夠直接使用將WebService方法的參數或返回值類型聲明成數組或類(接口)。但要注意,在定義數組類型時只能使用一維數組,若是想傳遞多維數組,可使用分隔符進行分隔,以下面的代碼所示: java
1
|
String[] strArray = new String[]{"自行車,飛機,火箭","中國,美國,德國", "超人,蜘蛛俠,鋼鐵俠" } ;
|
上面的代碼能夠看做是一個3*3的二維數組。 web
在傳遞類的對象實例時,除了直接將數組類型聲明成相應的類或接口,也能夠將對象實例進行序列化,也就是說,將一個對象實例轉換成字節數組進行傳遞,而後接收方再進行反序列化,還原這個對象實例。 正則表達式
下面的示例代碼演示瞭如何傳遞數組與類(接口)類型的數據,並演示如何使用字節數組上傳圖像。本示例的客戶端代碼使用Java和C#編寫。要完成這個例子須要以下幾步: apache
1、實現服務端代碼 數組
ComplexTypeService是一個WebService類,該類的代碼以下: app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
import java.io.FileOutputStream;
import 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();
}
}
|
2、實現DataForm類 webapp
DataForm是要返回的對象實例所對應的類,該類的實現代碼以下: this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package 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;
}
}
|
3、發佈WebService spa
因爲本示例的WebService類使用了一個Java類(DataForm類),所以,在發佈WebService以前,須要先將DataForm.class文件複製到<Tomcat安裝目錄>\webapps\axis2\WEB-INF\classes\data目錄中,而後將ComplexTypeService.class文件複製到<Tomcat安裝目錄>\webapps\axis2\WEB-INF\pojo目錄中,最後啓動Tomcat(若是Tomcat已經啓動,因爲增長了一個DataForm類,所以,須要從新啓動Tomcat)。 .net
4、使用Java編寫調用WebService的客戶端代碼
在客戶端仍然使用了RPC的調用方式,代碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
package 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 {
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("f:\\images.jpg");
java.io.FileInputStream fis = new java.io.FileInputStream("f:\\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");
data.DataForm df = (data.DataForm) serviceClient.invokeBlocking(opAddEntry, newObject[]{},
new Class[]{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[]{}, newClass[]{byte[].class})[0];
java.io.ObjectInputStream ois = new java.io.ObjectInputStream(
new java.io.ByteArrayInputStream(buffer));
df = (data.DataForm) ois.readObject();
System.out.println(df.getName());
//////////////////////////////////////////
}
}
|
運行上面的程序,將輸出以下的內容:
1
2
3
4
5
6
7
8
|
文件長度:3617
true
自行車 飛機 火箭
<自行車> <飛機> <火箭>
<中國> <美國> <德國>
<超人> <蜘蛛俠> <鋼鐵俠>
20
bill
|
5、使用C#編寫調用WebService的客戶端代碼
在Visual Studio中使用WebService就簡單得多。假設引用WebService時的引用名爲complexType,則下面的代碼調用了uploadImageWithByte方法來上傳圖像文件。在Visual Studio引用WebService時,uploadImageWithByte方法多了兩個out參數,在使用時要注意。
1
2
3
4
5
6
7
|
complexType.ComplexTypeService cts = new WSC.complexType.ComplexTypeService();
System.IO.FileStream fs = new System.IO.FileStream(@"f:\images.jpg", System.IO.FileMode.Open);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
bool r;
bool rs;
cts.uploadImageWithByte( buffer, (int)fs.Length, true, out r, out rs);
|
在得到二維數組時,能夠將數據加載到DataGridView或其餘相似的控件中,代碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
String[] strArray = cts.getMDArray();
for (int i = 0; i < strArray.Length; i++)
{
// 用正則表達式將帶分隔符的字符串轉換成String數組
String[] columns = strArray[i].Split(',');
// 若是DataGridView的表頭不存在,向DataGridView控件添加三個帶表頭的列
if (dataGridView1.Columns.Count == 0)
for (int j = 0; j < columns.Length; j++)
dataGridView1.Columns.Add("column" + (j + 1).ToString(), "列" + (j + 1).ToString());
// 添加行
dataGridView1.Rows.Add(1);
for(int j = 0; j < columns.Length; j++)
{
dataGridView1.Rows[i].Cells[j].Value = columns[j];
}
}
|
向DataGridView控件添加數據後的效果如圖1所示。
圖1
對於其餘的WebService方法的調用都很是簡單,讀者能夠本身作這個實驗。
要注意的是,因爲.net和java序列化和反序列化的差別,經過序列化的方式傳遞對象實例只使用於客戶端與服務端爲同一種語言或技術的狀況,如客戶端和服務端都使用Java來編寫。
若是讀者要上傳大文件,應儘可能使用FTP的方式來傳遞,而只經過WebService方法來傳遞文件名等信息。這樣有助於提升傳輸效率。