客戶端的調(diào)用
Web services提供的服務多種多樣,有的可以馬上獲得結(jié)果,有的要消耗很長的時間。所以,如果我們需要多種調(diào)用方式來對付不同的情況。
大多數(shù)的Web services都提供阻塞(Blocking)和非阻塞(Non-Blocking)兩種APIs.
這兩個概念以前應該學過,簡單說一下。
Blocking API - 調(diào)用端要等被調(diào)用的函數(shù)運行完畢才繼續(xù)往下走。
Non-Bloking API - 調(diào)用端運行完調(diào)用函數(shù)以后就直接往下走了,調(diào)用端和被調(diào)用端是異步執(zhí)行的。返回值是用回調(diào)函數(shù)來實現(xiàn)的。
這種異步叫做API層異步(API Level Asynchrony)。他們只用到一個連接來發(fā)送和接收消息,而且,如果是那種需要運行很長時間的函數(shù),還會碰到Time Out 錯誤,如果用兩個連接分別處理發(fā)送和接收消息,調(diào)用的時間就可以縮短,也可以解決Time Out 問題。用兩個連接來分別處理發(fā)送和接收消息,叫做傳輸層異步(Transport Level Asynchrony)。
理論真無聊,還是來看實例吧。
打開 Eclipse, 創(chuàng)建一個新Project, 新建一個叫userguide.clients的包, 把"samples\userguide\src\userguide\clients" 下面的文件都copy到那個包下面, 把AXIS2的lib下面的jar都加到ilbrary里面去(應該不用全加,懶一點就全加了吧.) 發(fā)現(xiàn)了關(guān)于echo的調(diào)用的方式, 居然有五個:
EchoBlockingClient
EchoBlockingDualClient
EchoBlockingWsaBasedClient
EchoNonBlockingClient
EchoNonBlockingDualClient
一個一個看吧.
EchoBlockingClient.java
public class EchoBlockingClient {
private static EndpointReference targetEPR = new EndpointReference("http://localhost:8080/axis2/services/MyService");
public static void main(String[] args) {
try {
OMElement payload = ClientUtil.getEchoOMElement();
Call call = new Call();
call.setTo(targetEPR);
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP,
false);
//Blocking invocation
OMElement result = call.invokeBlocking("echo",
payload);
StringWriter writer = new StringWriter();
result.serializeWithCache(XMLOutputFactory.newInstance()
.createXMLStreamWriter(writer));
writer.flush();
System.out.println(writer.toString());
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
}
和一代幾乎一樣, 弄一個EndpointReference, 再弄一個call, 其他不一樣,但是也很簡單, 弄一個OMElement作為參數(shù), 返回也是一個OMElement. 可惜運行居然有錯.
再來看雙通道的版本
EchoBlockingDualClient.java
public class EchoBlockingDualClient {
private static EndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/axis2/services/MyService");
public static void main(String[] args) {
try {
OMElement payload = ClientUtil.getEchoOMElement();
Call call = new Call();
call.setTo(targetEPR);
call.engageModule(new QName(Constants.MODULE_ADDRESSING));
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP,
true);
//Blocking Invocation
OMElement result = call.invokeBlocking("echo",
payload);
StringWriter writer = new StringWriter();
result.serializeWithCache(XMLOutputFactory.newInstance()
.createXMLStreamWriter(writer));
writer.flush();
System.out.println(writer.toString());
//Need to close the Client Side Listener.
call.close();
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
加了一句engageModule, 這句話好像沒什么用,我刪掉這句話也能運行的, 然后setTransportInfo最后一個參數(shù)改成了true. 關(guān)于setTransportInfo的三個參數(shù), 第一個是發(fā)送的Transport, 第二個是接收的Transport, 第三個是"是否雙通道", 支持的搭配形式如下:
http, http, true
http, http, false
http,smtp,true
smtp,http,true
smtp,smtp,true
看下一個吧,EchoNonBlockingClient,這個是單通道的非阻塞模式:
public class EchoNonBlockingClient {
private static EndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/axis2/services/MyService");
public static void main(String[] args) {
try {
OMElement payload = ClientUtil.getEchoOMElement();
Call call = new Call();
call.setTo(targetEPR);
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP,
false);
//Callback to handle the response
Callback callback = new Callback() {
public void onComplete(AsyncResult result) {
try {
StringWriter writer = new StringWriter();
result.getResponseEnvelope().serializeWithCache(XMLOutputFactory.newInstance()
.createXMLStreamWriter(writer));
writer.flush();
System.out.println(writer.toString());
} catch (XMLStreamException e) {
reportError(e);
}
}
public void reportError(Exception e) {
e.printStackTrace();
}
};
//Non-Blocking Invocation
call.invokeNonBlocking("echo", payload, callback);
//Wait till the callback receives the response.
while (!callback.isComplete()) {
Thread.sleep(1000);
}
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
不同的地方,只是調(diào)用的方法從invokeBlocking變成了invokeNonBlocking,然后寫了一個簡單的匿名Callback類作為回調(diào)函數(shù)。關(guān)于這個Callback類,它是一個抽象類,其中有兩個方法:onComplete和reportError,都是client端必須實現(xiàn)的,他還有一個Field,就是complete,可以用來設(shè)置和查詢調(diào)用是否完成。可惜也不能運行,和上面的錯誤一樣,是在createSOAPMessage的時候報null錯誤。
看下一個EchoNonBlockingDualClient,非阻塞的雙通道:
public class EchoNonBlockingDualClient {
private static EndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/axis2/services/MyService");
public static void main(String[] args) {
try {
OMElement payload = ClientUtil.getEchoOMElement();
Call call = new Call();
call.setTo(targetEPR);
//The boolean flag informs the axis2 engine to use two separate transport connection
//to retrieve the response.
call.engageModule(new QName(Constants.MODULE_ADDRESSING));
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP,
true);
//Callback to handle the response
Callback callback = new Callback() {
public void onComplete(AsyncResult result) {
try {
StringWriter writer = new StringWriter();
result.getResponseEnvelope().serializeWithCache(XMLOutputFactory.newInstance()
.createXMLStreamWriter(writer));
writer.flush();
System.out.println(writer.toString());
} catch (XMLStreamException e) {
reportError(e);
}
}
public void reportError(Exception e) {
e.printStackTrace();
}
};
//Non-Blocking Invocation
call.invokeNonBlocking("echo", payload, callback);
//Wait till the callback receives the response.
while (!callback.isComplete()) {
Thread.sleep(1000);
}
//Need to close the Client Side Listener.
call.close();
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
雙通道和單通道基本沒什么不同,只是雙通道的時候,它總是要