同步呼叫會阻塞客戶端執行緒,若服務端處理耗時(如範例中 Thread.sleep(5000)),使用者體驗極差。Axis2 提供兩種非同步機制解決此問題。
package service;
public class MyService {
public String getName() {
System.out.println("getName 正在執行");
try { Thread.sleep(5000); } catch (Exception ignored) {}
return "火星";
}
}
配置同樣使用 RPCMessageReceiver,無特殊設定。
package client;
import javax.xml.namespace.QName;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.rpc.client.RPCServiceClient;
public class RPCAsyncClient {
public static void main(String[] args) throws Exception {
RPCServiceClient client = new RPCServiceClient();
Options opts = client.getOptions();
opts.setTo(new EndpointReference("https://localhost:8080/axis2/services/myService"));
QName op = new QName("https://service", "getName");
client.invokeNonBlocking(op, new Object[]{}, new org.apache.axis2.client.async.AxisCallback() {
@Override public void onComplete() {}
@Override public void onError(Exception e) {}
@Override public void onFault(MessageContext ctx) {}
@Override public void onMessage(MessageContext ctx) {
// 解析回應:Envelope → Body → getNameResponse → return
System.out.println(ctx.getEnvelope().getFirstElement()
.getFirstElement().getFirstElement().getText());
}
});
System.out.println("非同步呼叫已發送!");
System.in.read(); // 防止主執行緒結束
}
}
輸出:
非同步呼叫已發送! 火星
%AXIS2_HOME%\bin\wsdl2java -uri https://localhost:8080/axis2/services/myService?wsdl \
-p client -s -a -o stub
-s 產生同步 Stub-a 產生非同步 Callback Handler產生 MyServiceStub 與抽象類 MyServiceCallbackHandler。
package client;
import client.MyServiceStub.GetNameResponse;
class MyCallback extends MyServiceCallbackHandler {
@Override public void receiveResultgetName(GetNameResponse result) {
System.out.println(result.get_return());
}
}
public class StubClient {
public static void main(String[] args) throws Exception {
MyServiceStub stub = new MyServiceStub();
stub.startgetName(new MyCallback());
System.out.println("非同步呼叫已發送!");
System.in.read();
}
}
// 回調方法
private void getNameCompletedEvent(object sender, WSC.asyn.getNameCompletedEventArgs e) {
listBox1.Items.Add(e.Result.@return);
}
private void button1_Click(object sender, EventArgs e) {
async.myService svc = new WSC.async.myService();
svc.getNameCompleted += getNameCompletedEvent;
svc.getNameAsync();
MessageBox.Show("呼叫已發送,UI 未凍結");
}
注意:同一服務實例不可並發呼叫同一方法(會拋例外),需新建實例或等待完成。
| 場景 | 建議 |
|---|---|
| 快速原型、動態端點 | RPCServiceClient |
| 正式專案、強型別、IDE 提示 | wsdl2java 產生 Stub |
| .NET 客戶端 | 原生 async/await 或 Event-based Async Pattern |
非同步呼叫是提升 Web Service 客戶端回應性的關鍵,Axis2 同時支援程式化與程式碼產生兩條路徑,按專案需求選擇。