最近完成一個與IBM的醫院融合項目,使用webservice特此總結。從axis2、xfire、cxf框架中選擇了axis2原因是之前一個項目也使用axis2。
1、首先從http://axis.apache.org/axis2/java/core/download.cgi下載最新的axis2,下載Binary Distribution zip | MD5 | PGP 和 WAR Distribution zip | MD5 | PGP 。其中WAR文件必須放入web容器的webapps里(專業點就是放入servlet engine里)因為發布的webservice都構建在此基礎上,就好比web項目要運行在J2EE容器里面一樣。文章結尾將會說明不需要部署該WAR文件,在一個自己的項目里面部署axis2并發布webservice。
2、使用axis2讓人難于理解的地方,(個人感覺)不是寫services代碼,也不是寫Client測試代碼。而是如何配置services.xml文件,以及發布成aar文件。在說明這個問題前首先要說明下axis2處理xml的機制,Axis1.x使用DOM作為其XML表示機制,但使用DOM的缺點是:需要在內存中保存完整的對象層次結構,對于小消息,這將不是問題,但對于大型消息就是問題了。為解決這個問題,Axis2引入了新的XML表示形式即AXIOM(Axis2 Object Model),任何SOAP消息在Axis2中都表示為AXIOM。它基于Pull解析器技術,即調用者對解析器具有完全控制權,可以要求觸發下一個事件,因此具有“隨需應變構建”功能,僅在被要求時才會構建對象模型。
下面對services,xml文件以及如何發布成aar進行簡單說明(代碼均來自官方網站)首先創建一個簡單的java類(用于發布成webservice)
1
package samples.quickstart.service.pojo;
2
3
import java.util.HashMap;
4
5
public class StockQuoteService
{
6
private HashMap map = new HashMap();
7
8
public double getPrice(String symbol)
{
9
Double price = (Double) map.get(symbol);
10
if(price != null)
{
11
return price.doubleValue();
12
}
13
return 42.00;
14
}
15
16
public void update(String symbol, double price)
{
17
map.put(symbol, new Double(price));
18
}
19
}
上面代碼很簡單接著給出services.xml文件
1
<service name="StockQuoteService" scope="application">
2
<description>
3
Stock Quote Sample Service
4
</description>
5
<messageReceivers>
6
<messageReceiver
7
mep="http://www.w3.org/2004/08/wsdl/in-only"
8
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
9
<messageReceiver
10
mep="http://www.w3.org/2004/08/wsdl/in-out"
11
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
12
</messageReceivers>
13
<parameter name="ServiceClass">
14
samples.quickstart.service.pojo.StockQuoteService
15
</parameter>
16
</service>
service元素里面的name屬性代表該webservice的訪問名字
messageReceivers元素定義用于處理此操作的消息接收器。
打包:
Axis2服務是作為Axis Archive(.aar)打包的 。這是一個jar文件,打包后具有以下結構:
1
./stock/StockQuoteService.class
2
3
./META-INF/services.xml
使用MyEclipse,首先選中StockQuoteService和META-INF/services.xml然后Export成.aar文件后,里面的META-INF文件夾里面不存在services.xml需要將WebRoot/META-INF里面的services挪進aar根目錄的META-INF里面。
最后將該aar文件放入web容器webapps/axis2/WEB-INF/services里面,啟動web容器,訪問
http://localhost:8080/axis2/services/StockQuoteService?wsdl
這樣webservice服務發布成功,但是以上發布沒有基于SOAP標準。
下面給出的services代碼以及Client代碼都基于AXIOM的API(代碼均來自官方網站示例)首先還是構建一個java類(使用AXIOM用于發布成webservice)
1
package samples.quickstart.service.axiom;
2
3
import javax.xml.stream.XMLStreamException;
4
import org.apache.axiom.om.OMAbstractFactory;
5
import org.apache.axiom.om.OMElement;
6
import org.apache.axiom.om.OMFactory;
7
import org.apache.axiom.om.OMNamespace;
8
9
import java.util.HashMap;
10
public class StockQuoteService
{
11
private HashMap map = new HashMap();
12
13
public OMElement getPrice(OMElement element) throws XMLStreamException
{
14
element.build();
15
element.detach();
16
17
OMElement symbolElement = element.getFirstElement();
18
String symbol = symbolElement.getText();
19
20
String returnText = "42";
21
Double price = (Double) map.get(symbol);
22
if(price != null)
{
23
returnText = "" + price.doubleValue();
24
}
25
OMFactory fac = OMAbstractFactory.getOMFactory();
26
OMNamespace omNs =
27
fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
28
OMElement method = fac.createOMElement("getPriceResponse", omNs);
29
OMElement value = fac.createOMElement("price", omNs);
30
value.addChild(fac.createOMText(value, returnText));
31
method.addChild(value);
32
return method;
33
}
34
35
public void update(OMElement element) throws XMLStreamException
{
36
element.build();
37
element.detach();
38
39
OMElement symbolElement = element.getFirstElement();
40
String symbol = symbolElement.getText();
41
42
OMElement priceElement = (OMElement)symbolElement.getNextOMSibling();
43
String price = priceElement.getText();
44
45
map.put(symbol, new Double(price));
46
}
47
}
上面17-18行代碼表示獲取請求參數
25-31行代碼表示創建響應消息
update方法里面的代碼類似。
下面是services.xml文件內容
1
<service name="StockQuoteService" scope="application">
2
<description>
3
Stock Quote Service
4
</description>
5
<operation name="getPrice">
6
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
7
</operation>
8
<operation name="update">
9
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
10
</operation>
11
<parameter name="ServiceClass">samples.quickstart.service.axiom.StockQuoteService</parameter>
12
</service>
service元素里面name屬性代表webservice的訪問名
operation元素里面的name屬性代表方法
parameter元素里面的name屬性(固定值ServiceClass)代表自定義的包名.類名
messageReceiver元素定義用于處理此操作的消息接收器。Axis針對In-Only和In-Out操作提供了兩個無數據綁定的內置MessageReceivers;
org.apache.axis2.reveivers.RawXMLINOnlyMessageReceiver用于In-Only操作
org.apache.axis2.reveivers.RawXMLOutOnlyMessageReceiver用于In-Out操作
如果沒有指定messageReceiver,則Axis2將嘗試使用org.apache.axis2.reveivers.RawXMLINOutMessageReceiver作為缺省的messageReceiver。
上述RAWXML消息接收器將傳入SOAP消息的<Body>的內容作為OMElement傳遞給服務實現。此操作應作為OMElement返回SOAP響應的<Body>元素包含的XML內容。這就解釋了上述方法返回值為什么是OMElement了
打包過程同上。啟動web容器,訪問http://localhost:8080/axis2/services/StockQuoteService?wsdl即可訪問
客戶端測試代碼:
1
package samples.quickstart.clients;
2
3
import org.apache.axiom.om.OMAbstractFactory;
4
import org.apache.axiom.om.OMElement;
5
import org.apache.axiom.om.OMFactory;
6
import org.apache.axiom.om.OMNamespace;
7
import org.apache.axis2.Constants;
8
import org.apache.axis2.addressing.EndpointReference;
9
import org.apache.axis2.client.Options;
10
import org.apache.axis2.client.ServiceClient;
11
12
public class AXIOMClient
{
13
14
private static EndpointReference targetEPR =
15
new EndpointReference("http://localhost:8080/axis2/services/StockQuoteService");
16
17
public static OMElement getPricePayload(String symbol)
{
18
OMFactory fac = OMAbstractFactory.getOMFactory();
19
OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
20
21
OMElement method = fac.createOMElement("getPrice", omNs);
22
OMElement value = fac.createOMElement("symbol", omNs);
23
value.addChild(fac.createOMText(value, symbol));
24
method.addChild(value);
25
return method;
26
}
27
28
public static OMElement updatePayload(String symbol, double price)
{
29
OMFactory fac = OMAbstractFactory.getOMFactory();
30
OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
31
32
OMElement method = fac.createOMElement("update", omNs);
33
34
OMElement value1 = fac.createOMElement("symbol", omNs);
35
value1.addChild(fac.createOMText(value1, symbol));
36
method.addChild(value1);
37
38
OMElement value2 = fac.createOMElement("price", omNs);
39
value2.addChild(fac.createOMText(value2,
40
Double.toString(price)));
41
method.addChild(value2);
42
return method;
43
}
44
45
public static void main(String[] args)
{
46
try
{
47
OMElement getPricePayload = getPricePayload("WSO");
48
OMElement updatePayload = updatePayload("WSO", 123.42);
49
Options options = new Options();
50
options.setTo(targetEPR);
51
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
52
53
ServiceClient sender = new ServiceClient();
54
sender.setOptions(options);
55
56
sender.fireAndForget(updatePayload);
57
System.err.println("price updated");
58
OMElement result = sender.sendReceive(getPricePayload);
59
60
String response = result.getFirstElement().getText();
61
System.err.println("Current price of WSO: " + response);
62
63
} catch (Exception e)
{
64
e.printStackTrace();
65
}
66
}
67
68
}
最后如果想得到某個已經寫好的服務類的wsdl描述文件,使用java2wsdl工具。
首先配置Axis2_HOME路徑(名字必須是這樣,否則配置較麻煩),然后配置PATH添加%Axis2_HOME%\bin,最后打開dos窗口(如果需要對test.class文件生成wsdl描述符),那么進入該Test.class根目錄下一般就是在classes目錄,輸入java2wsdl -cp . -cn 包名.Test -of Test.wsdl執行成功后會在classes根目錄生成wsdl文件,可以交給對方生成客戶端測試代碼,此次與IBM融合就使用這種方法。
未完待續。。。
posted on 2011-03-04 17:08
朔望魔刃 閱讀(2982)
評論(0) 編輯 收藏