開發回傳字串陣列、物件、以及物件陣列的服務
This document is provided as is. You are welcomed to use it for non-commercial purpose.Written by: 國立中興大學資管系呂瑞麟
請勿轉貼
在之前的範例中,我們可以觀察到只要交換資料的資料型態是基本資料型態 (如 short, int, float, double 等)以及字串,client 的程式都非常 簡單。可是如果是陣列,或者物件(尤其是日期的物件),程式的開發有沒有 困難?
- 開發一個會回傳字串陣列的服務,該服務提供一 String[] getTimeArray(String[] input) operation,而該 operation 接受一個字串陣列的參數,並將回傳一
字串陣列。
- 服務端:StringArray.java
import java.util.*; public class StringArray { private String[] date; public StringArray() { Calendar now = Calendar.getInstance(); date = new String[6]; date[0] = String.valueOf(now.get(Calendar.YEAR)); date[1] = String.valueOf(now.get(Calendar.MONTH) + 1); date[2] = String.valueOf(now.get(Calendar.DATE)); date[3] = String.valueOf(now.get(Calendar.HOUR)); date[4] = String.valueOf(now.get(Calendar.MINUTE)); date[5] = String.valueOf(now.get(Calendar.SECOND)); } public String[] getTimeArray(String[] input) { for(int i=0; i<date.length; i++) { date[i] = date[i] + " " + input[i]; } return date; } }
- 產生一個註冊用的 WSDD 檔並註冊,跟之前的類似,故省略。
- 利用 WSDL2Java 產生必要的 proxy 類別,跟之前的類似,故省略。
- 產生客戶端程式:ArrayClient.java
import java.rmi.*; import javax.xml.rpc.*; import localhost.axis.services.StrArrayService.*; public class ArrayClient { public static void main(String[] args) throws RemoteException, ServiceException { StringArrayService service = new StringArrayServiceLocator(); StringArray call = service.getStrArrayService(); String[] input = {"年","月","日","時","分","秒"}; String[] result = call.getTimeArray(input); for(int i=0; i<result.length; i++) System.out.print(result[i] + " "); System.out.println(); } }
- 服務端:StringArray.java
- 開發一個回傳物件以及物件陣列的服務,該服務提供 Worker getWorker()、Worker[] getArray()、以及 void setWorker(Worker w) 的 operations.
- 服務端:WorkerService.java
import java.util.*; public class WorkerService { private Worker worker; public WorkerService() { worker = new Worker(); } public Worker getWorker() { return worker; } public void setWorker(Worker w) { worker = w; } public Worker[] getArray() { Calendar c = Calendar.getInstance(); c.set(1978, Calendar.MAY, 17); Worker w2 = new Worker("Dave Mentis", 60, c); Worker[] w = {new Worker(), w2}; return w; } }
- 自訂的類別: Worker.java(為了避免麻煩,我們將 Worker.java 依據 JavaBean
的規範設計,細節討論,請參考 AXIS 與 .NET 互通性)。另外,我們在 Worker.java
也增加了一個日期的資料成員,根據經驗,請不要使用 java.util.Date,而應該使用
java.util.Calendar 或者 java.util.GregorianCalendar。請注意,所謂 JavaBean
的設計規範是說:當開發人員設計一個類別時,請務必設計該類別的預設建構元、
包含所有資料成員當作參數的建構元、以及每一個資料成員都有一對 get/set 方法。
以 Worker.java 為例,由於它有三個資料成員,所以我們需要設計出一個預設建構元
public Worker()、包含所有資料成員當作參數的建構元 public Worker(String n, int h, Calendar c)、資料成員 name 有一對 setName()/getName() 方法、資料成員 hours
有一對 setHours()/getHours() 方法、以及資料成員 birthday 有一對
setBirthday()/getBirthday() 方法。
import java.util.*; public class Worker { private String name; private int hours; private Calendar birthday; public Worker() { name = "Eric Lu"; hours = 40; birthday = Calendar.getInstance(); birthday.set(1988, Calendar.JULY, 15); } public Worker(String n, int h, Calendar c) { setName(n); setHours(h); setBirthday(c); } public String getName() { return name; } public int getHours() { return hours; } public Calendar getBirthday() { return birthday; } public void setName(String n) { name = n; } public void setHours(int h) { hours = h; } public void setBirthday(Calendar d) { birthday = d; } }
- WSDD 檔:由於在 WorkerService 中,使用了自訂的類別 Worker,因此在
WSDD 的定義上,需要增加 beanMapping 的定義,該定義會使得 WSDL2Java 產生
恰當的 Worker 檔在 client 端。另外,由於 WSDL 檔內的 targetNamespace
是預設的 http://DefaultNamespace,最好在定義 beanMapping 的時候,
也設定適當的命名空間。
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="ObjectService" provider="java:RPC" style="wrapped" use="literal"> <parameter name="className" value="WorkerService" /> <parameter name="allowedMethods" value="*" /> <beanMapping qname="tns:Worker" xmlns:tns="http://DefaultNamespace" languageSpecificType="java:Worker" /> </service> </deployment>
- 客戶端程式 WorkerClient.java:過程跟之前所說的一樣,先利用 WSDL2Java
以及 service 的 WSDL 檔來產生 proxy 類別,然後把這些類別 import 到客戶端程式
即可。跟之前的範例有一點不太一樣的地方是,這次我們定義了 Worker,
由於我們在 WSDD 內定義它的 namespace 是 DefaultNamespace,因此 WSDL2Java
會產生一個 Worker.java 的程式在 DefaultNamespace 的子目錄內。
import java.rmi.*; import javax.xml.rpc.*; import localhost.axis.services.ObjectService.*; import DefaultNamespace.*; import java.util.*; public class WorkerClient { public static void main(String[] args) throws RemoteException, ServiceException { WorkerServiceService service = new WorkerServiceServiceLocator(); WorkerService call = service.getObjectService(); // 先利用 service 設定一個 Worker 物件 Calendar c = Calendar.getInstance(); c.set(1970, Calendar.JUNE, 22); Worker s = new Worker(c, 55, "Mary Ann"); call.setWorker(s); // 再取回剛剛的 Worker 物件(???) Worker w = call.getWorker(); System.out.print(w.getName() + "\t"); System.out.print(w.getHours() + "\t"); c = w.getBirthday(); System.out.println(c.get(Calendar.YEAR) + "/" + (c.get(Calendar.MONTH) + 1) + "/" + c.get(Calendar.DATE) + "\n"); // 取得一個預設的 Worker[] 陣列 Worker[] ww = call.getArray(); for(int i=0; i < ww.length; i++) { System.out.print(ww[i].getName() + "\t"); System.out.print(ww[i].getHours() + "\t"); c = ww[i].getBirthday(); System.out.println(c.get(Calendar.YEAR) + "/" + (c.get(Calendar.MONTH) + 1) + "/" + c.get(Calendar.DATE)); } } }
依據 Axis 的文件,上述情形(每次呼叫 service,該 service 物件都會 重新被產生)稱之為 "request",這是 Axis 的預設行為;Axis 還提供其它 兩種行為模式:一個是 "session"(每一個 session 只有一個 service 物件), 另一個是 "application"(這個 client application 都只使用一個 service 物件)。 由於有可能會有多個程式同時呼叫該 service 物件的方法,使用 "session" 和 "application" 的開發人員必須自行控制可能發生的情形。
若需要更改 service 物件的產生方式會以 application 為 scope,我們需要 更改 wsdd 的內容,更新後的 WSDD 檔的內容如下:
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="ObjectService" provider="java:RPC" style="wrapped" use="literal"> <parameter name="scope" value="Application" /> <parameter name="className" value="WorkerService" /> <parameter name="allowedMethods" value="*" /> <beanMapping qname="tns:Worker" xmlns:tns="http://DefaultNamespace" languageSpecificType="java:Worker" /> </service> </deployment>
- 服務端:WorkerService.java
Written by: 國立中興大學資管系呂瑞麟
沒有留言:
張貼留言