標籤:
本章主要介紹axis2介面的非同步呼叫方式。
一般情況下,我們使用同步方法(invokeBlocking)調用axis2介面,如果被調用的WebService方法長時間不返回,用戶端將一直被阻塞,直到該方法返回為止。使用同步方法來調用WebService雖然很直觀,但當WebService方法由於各種原因需要很長時間才能返回的話,就會使用戶端程式一直處於等待狀態,這樣使用者是無法忍受的。
當然,我們很容易就可以想到解決問題的方法,這就是多線程。解決問題的基本方法是將訪問WebService的任務交由一個或多個線程來完成,而主線程並不負責訪問WebService。這樣即使被訪問的WebService方法長時間不返回,用戶端仍然可以做其他的工作。我們可以管這種通過多線程訪問WebService的方式稱為非同步訪問。
雖然直接使用多線程可以很好地解決這個問題,但比較麻煩。幸好Axis2的用戶端提供了非同步訪問WebService的功能。
RPCServiceClient類提供了一個invokeNonBlocking方法可以通過非同步方式來訪問WebService。下面結合一個執行個體程式說明。
目錄結構:
關鍵代碼:
package com.alfred.client;import java.io.IOException;import javax.xml.namespace.QName;import org.apache.axis2.addressing.EndpointReference;import org.apache.axis2.client.Options;import org.apache.axis2.client.async.AxisCallback;import org.apache.axis2.context.MessageContext;import org.apache.axis2.rpc.client.RPCServiceClient;public class ServiceClient {public static void main(String args[]) throws IOException {sendAxis2();}/** * 發送axis2的介面資訊 * * @throws IOException */private static void sendAxis2() throws IOException {// 使用RPC方式調用WebServiceRPCServiceClient serviceClient = new RPCServiceClient();Options options = serviceClient.getOptions();// 指定調用WebService的URLEndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/awyb/services/mySoapService");options.setTo(targetEPR);// 指定sayHello方法的參數值,如果有多個,繼續往後面增加即可Object[] opAddEntryArgs = new Object[] { "alfred" };// 在建立QName對象時,QName類的構造方法的第一個參數表示WSDL,檔案的命名空間名,也就是<wsdl:definitions>元素的targetNamespace屬性值// 第二個參數是要調用的方法名QName opAddEntry = new QName("http://service.alfred.com", "sayHello");serviceClient.invokeNonBlocking(opAddEntry, opAddEntryArgs,new AxisCallback() {public void onComplete() {}public void onError(Exception arg0) {}public void onFault(MessageContext arg0) {}public void onMessage(MessageContext mc) {// 輸出傳回值System.out.println(mc.getEnvelope().getFirstElement().getFirstElement().getFirstElement().getText());}});System.out.println("非同步呼叫!");// 阻止程式退出System.in.read();}}ServiceClient.java
package com.alfred.service;import org.apache.axis2.AxisFault;public class SoapService {public String sayHello(String name) throws AxisFault {try {System.out.println("sayHello方法正在執行 ");// 延遲5秒Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}return "Hello," + name;}public String getWorld() {return "Hello,World";}}SoapService.java
用戶端非同步訪問axis2的sayHello,控制台列印資訊:
可以看到程式並沒有等待介面返回就繼續執行之後的操作。
非同步呼叫使用的方法是invokeNonBlocking,從上面的代碼可以看出,invokeNonBlocking方法有三個參數,前兩個參數分別指定了要調用的方法及方法參數的相關資訊,而最後一個參數並不是方法傳回值的類型資訊,而是一個實現org.apache.axis2.client.async.AxisCallback介面的類的對象執行個體。在本例中隱式實現了AxisCallback介面。在AxisCallback介面中有四個方法需要實現,其中當被非同步呼叫的方法返回時onMessage方法被調用。
我們也可以使用wsdl2java命令的-a參數產生可非同步呼叫的Stub類(需先安裝axis2,配置好AXIS2_HOME環境變數)。下面的命令可產生同步和非同步呼叫的用戶端代碼(兩個類),其中-s表示產生同步調用代碼,-a表示產生非同步呼叫代碼。
%AXIS2_HOME%\bin\wsdl2java -uri http://127.0.0.1:8080/awyb/services/mySoapService?wsdl -p client -s -a -o stub
在執行上面的命令後,將產生兩個類:MySoapServiceStub和MySoapServiceCallbackHandler類,其中MySoapServiceStub類負責同步和非同步呼叫WebService,MySoapServiceCallbackHandler類是一個抽象類別,也是一個回調類,當使用非同步方式調用WebService方法時,如果方法返回,則MySoapServiceCallbackHandler類的receiveResultgetName方法被調用。下面是使用MySoapServiceStub類非同步訪問WebService的代碼。
目錄結構:
關鍵代碼:
package client;import client.MySoapServiceStub.GetWorldResponse;import client.MySoapServiceStub.SayHelloResponse;public class MyCallback extends MySoapServiceCallbackHandler {@Overridepublic void receiveResultgetWorld(GetWorldResponse result) {// 輸出getWorld方法的返回結果System.out.println(result.get_return());}@Overridepublic void receiveResultsayHello(SayHelloResponse result) {// 輸出sayHello方法的返回結果System.out.println(result.get_return());}}MyCallback.java
package client;import client.MySoapServiceStub.SayHello;public class StubClient {public static void main(String[] args) throws Exception {MySoapServiceStub stub = new MySoapServiceStub();// 非同步呼叫WebServiceSayHello sayHello = new SayHello();sayHello.setName("alfred other");stub.startsayHello(sayHello, new MyCallback());System.out.println("非同步呼叫!");System.in.read();}}StubClient.java
MySoapServiceCallbackHandler和MySoapServiceStub是自動產生的程式碼。
訪問sayHello後控制台列印結果:
Axis2之非同步呼叫