日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通向架构师的道路(第十天)之Axis2 Web Service(一)

發布時間:2024/4/14 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通向架构师的道路(第十天)之Axis2 Web Service(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、Axis2簡介

1.1?介紹Axis2

Axis框架來自 Apache 開放源代碼組織,它是基于Java語言的最新的 SOAP 規范(SOAP 1.2)和 SOAP withAttachments 規范(來自 Apache Group )的開放源代碼實現。有很多流行的開發工具都使用AXIS作為其實現支持Web服務的功能,例如JBuilder以及著名的Eclipse J2EE插件Lomboz。AXIS的最新版本可以從 http://ws.apache.org/axis/index.html下載。

下載下來后直接解壓即可用了。下圖是AXIS核心引擎的體系結構圖:

整個AXIS項目包括以下幾個部分:

ü?? 消息流子系統

消息流子系統提供了靈活的消息傳遞框架,這個消息傳遞框架包括處理程序、鏈、序列化程序和反序列化程序。處理程序是一個處理請求、響應和故障流的對象。處理程序可被組合在一起成為鏈,而且可以使用一個靈活的部署描述符來配置這些處理程序的順序。

ü?? 傳輸框架子系統

提供了一個傳輸框架,這個傳輸框架可以幫助您創建自己的可插式傳輸發送器和傳輸偵聽器。

ü?? 數據編碼子系統

AXIS完全按照 XML Schema 規范提供各種數據類型的自動序列化,并且提供功能擴展接口來使用您自己定制的序列化器和反序列化器。

ü?? 其他

AXIS完全支持 WSDL 以及日志記錄、出錯以及故障處理機制。它同時提供一些工具用來講WSDL文檔轉換成客戶端的調用框架以及根據類來產生WSDL定義文檔。

AXIS目前版本支持的標準是:W3C SOAP1.1 和 1.2;WSDL 1.1;SAAJ 1.1(SUN公司:SOAP with Attachments API for Java);JAX-RPC(SUN公司:Java?APIfor XML-Based RPC)1.0。

1.2?開發項目中如何選擇使用Axis2和其它的WebService

2? 如果你的應用程序需要支持多語言即有C++, .net, Java,你應該選擇Axis2。

2 如果應用程序是遵循?spring?哲學路線的話,ApacheCXF 或者Spring WS是一種更好的選擇,特別對嵌入式的 Web Services 來說。

一、搭建環境

第一步:

打開Eclipse,建立一個標準的Dynamic Web Project

第二步:

建完工程后,把Axis2-1.4/Axis2-1.4.1解壓開來的目錄下的axis2-web(如下圖),整個拷入你工程的WebContent目錄下:

第三步:

把Axis2-1.4/Axis2-1.4.1解壓開來的目錄下的lib目錄里的所有jar導入你工程的WEB-INF/lib目錄下,并加載入工程的classpath,如下圖

第四步:

在工程和src平級處新建一個目錄叫external-lib


第五步:

把tomcat里的用于jsp, servlet解析的兩個lib拷入此external-lib目錄,并且以“加載外部jar”的方式加入工程的classpath中去

第六步:

在工程的WEB-INF目錄下新建一個目錄叫services目錄。

第七步:

把Axis2-1.4/Axis2-1.4.1解壓開來的目錄下的repository\modules,modules這個目錄,整個拷貝到你工程的WEB-INF目錄下。

整個配完的工程結構應如下圖所示:

三、??? 第一個Axis2Webservice之HelloWorld

3.1Service端代碼

package org.sky.axis2.helloworld;

import org.apache.axiom.om.OMElement;

import org.apache.axis2.AxisFault;

import javax.xml.stream.XMLStreamException;

public class HelloWorld {

???????? public OMElement sayHello(OMElement element) throws XMLStreamException {

?????????????????? element.build();

?????????????????? // Secondly the OMElement should be detached from the current OMTree so

?????????????????? // that it can be attached

?????????????????? // some other OM Tree. Once detached the OmTree will remove its

?????????????????? // connections to this OMElement.

?????????????????? element.detach();

?????????????????? return element;

???????? }

}

3.2 Service端的Web Service布署文件

然后我們在工程的WebContent\WEB-INF\services\目錄下新建一個目錄叫HelloWorld的目錄,與我們的類同名,在此目錄下再建立一個META-INF的目錄(大小寫必須完全一致),然后在META-INF目錄下新建一個services.xml,具體目錄結構如下圖所示:

Services.xml文件的內容如下:

<service name="HelloWorld">

???????? <parameter name="ServiceClass">org.sky.axis2.helloworld.HelloWorld</parameter>

??? <operation name="sayHello">

??????? <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>

??????? <actionMapping>urn:sayHello</actionMapping>

??? </operation>

</service>

該布署文件很容易閱讀:

1)????? 它聲明了一個WebService的主類叫” org.sky.axis2.helloworld.HelloWorld”;

2)????? 該WebService有一個Web Service Method,在類中該方法名叫sayHello,它返回一個OMElement為類型的值,接受一個OMElement為類型的參數;(RawXMLINOutMessageReceiver)

3)????? sayHello這個對外暴露的WebService方法名為: urn:sayHello

修改web.xml,在里面加入這些東東:

<servlet>
??? <display-name>Apache-Axis Servlet</display-name>
??? <servlet-name>AxisServlet</servlet-name>
??? <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class>
? </servlet>
? <servlet-mapping>
??? <servlet-name>AxisServlet</servlet-name>
??? <url-pattern>/servlet/AxisServlet</url-pattern>
? </servlet-mapping>
? <servlet-mapping>
??? <servlet-name>AxisServlet</servlet-name>
??? <url-pattern>*.jws</url-pattern>
? </servlet-mapping>
? <servlet-mapping>
??? <servlet-name>AxisServlet</servlet-name>
??? <url-pattern>/services/*</url-pattern>
? </servlet-mapping>
? <servlet>
??? <display-name>Apache-Axis Admin Servlet Web Admin</display-name>
??? <servlet-name>AxisAdminServlet</servlet-name>
??? <servlet-class>org.apache.axis2.transport.http.AxisAdminServlet</servlet-class>
??? <load-on-startup>100</load-on-startup>
? </servlet>
? <servlet-mapping>
??? <servlet-name>AxisAdminServlet</servlet-name>
??? <url-pattern>/axis2-admin/*</url-pattern>
? </servlet-mapping>

3.3?布署Web Service

在Tomcat的webapps目錄下建立一個目錄叫Axis2Service的目錄

然后將整個工程的WebContent目錄下的所有東西,全拷貝入這個目錄內,啟動tomcat。

啟動后訪問:http://localhost:8080/Axis2Service/axis2-web/

單點:Services這個鏈接

再點這個HelloWorld鏈接

我們就可以得到我們的HelloWorld這個WebService的wsdl內容了。

三、??? 四種不同的HelloWorld客戶端

Axis2支持4種類型的客戶端:

ü?? Block(阻塞式客戶端)

傳統客戶端

ü?? Non block(非阻塞式客戶端)

又被稱為異步客戶端,傳統客戶端被調用后將會被阻塞直到操作完成。這種方式在有很多Web Service需要在一個單一的客戶端應用程序中啟動時很不可取。一種解決方法是使用Non-Blocking API來調用這些Web Services。Axis2提供給用戶一種基于回叫機制的non-blocking API。

ü?? 雙工(雙向傳輸)

以上的機制都使用單一的連接去發送請求和接收響應.這都明顯在性能上落后于使用兩條連接(單向或雙向)進行進行請求和響應的傳輸 . 因此以上的機制都不能解決長時間運行的交易, 連接將在操作還沒完成就會超時. 一種解決方案是使用分開的兩條傳輸連接來傳輸請求和響應 . 我們叫這種方案為傳輸層異步。

ü?? 雙工非阻塞(雙向且非阻塞傳輸)

下面我們就來看這四個客戶端(此處對于雙工傳輸的客戶端代碼進行忽略,因為這個寫法很簡單,我們將著重于描述雙工+非阻塞的客戶端例子,網上目前幾乎沒有能夠在axis21.4下真正能夠運行的“雙工且非阻塞”的例子或者是完整代碼)。

4.1?傳統的客戶端HelloWorldWithReturnClient.java

package org.sky.axis2.helloworld;

import java.util.Iterator;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMAbstractFactory;

import org.apache.axiom.om.OMElement;

import org.apache.axiom.om.OMFactory;

import org.apache.axiom.om.OMNamespace;

import org.apache.axiom.om.OMNode;

import org.apache.axiom.soap.SOAPBody;

import org.apache.axis2.AxisFault;

import org.apache.axis2.addressing.EndpointReference;

import org.apache.axis2.client.Options;

import org.apache.axis2.client.ServiceClient;

import org.apache.axis2.databinding.utils.BeanUtil;

import org.apache.axis2.engine.DefaultObjectSupplier;

public class HelloWorldWithReturnClient {

???????? private static?EndpointReference targetEPR = new EndpointReference(

??????????????????????????? "http://localhost:8080/Axis2Service/services/HelloWorld");

???????? public void sayHello() {

?????????????????? Options options = new Options();

???????????????????options.setAction("urn:sayHello");

?????????????????? options.setTo(targetEPR);

?????????????????? ServiceClient sender = null;

?????????????????? try {

??????????????????????????? sender = new ServiceClient();

??????????????????????????? sender.setOptions(options);

??????????????????????????? OMFactory fac = OMAbstractFactory.getOMFactory();

????????????????????????????OMNamespace omNs = fac

?????????????????????????????????????????????? .createOMNamespace("http://helloworld.axis2.sky.org", "");

????????????????????????????OMElement method = fac.createOMElement("sayHello", omNs);

??????????????????????????? OMElement name = fac.createOMElement("name", omNs);

??????????????????????????? name.setText("ymk");

??????????????????????????? method.addChild(name);

????????????????????????????method.build();

??????????????????????????? OMElement response = sender.sendReceive(method);

??????????????????????????? System.out.println(response);

????????????????????????????OMElement element = response.getFirstChildWithName(

?????????????????????????????????????????????? new QName("http://helloworld.axis2.sky.org", "name"));

??????????????????????????? System.out.println(element.getText());

?????????????????? } catch (AxisFault e) {

??????????????????????????? System.out.println("------Error Occured------");

??????????????????????????? e.printStackTrace();

?????????????????? }

???????? }

???????? public static void main(String[] args) {

?????????????????? HelloWorldWithReturnClient testClient = new HelloWorldWithReturnClient();

?????????????????? testClient.sayHello();

???????? }

}

注意我加粗或者是加粗標紅處的代碼,為核心代碼。

由于我們使用提Axis2的底層API來調用WebService而并不是像傻瓜式的通過一個wsdl生成Web Service調用句柄,所以我們要對一個WSDL能夠有閱讀能力。

ü???Axis2中的Webservice的入口

不是:?http://localhost:8080/Axis2Service/services/HelloWorld?wsdl這個哦,而應該是:

http://localhost:8080/Axis2Service/services/HelloWorld,不帶?wsdl。

ü???看一個wsdl中的namespace是什么:

ü???看一個wsdl中的web service方法名是什么


ü???看一個wsdl的返回結果是怎么樣的格式:

為此我們在程序里增加了一行:OMElement response =sender.sendReceive(method);

然后直接:System.out.println(response);

這樣,我們可以看到它的返回為:

根據Axis2的OMElement的解析語法我們就可以直接把這個返回的值get出來。

我們甚至可以用opensource的SOAP UI這個工具,來直接得到我們的webservice調用的返回值,并以此返回結果的格式來決定我們如何去解析這個OMElement格式的返回結果:

在工程上單擊右鍵選“AddWSDL”


在彈出對話框中直接把http://localhost:8080/Axis2Service/services/HelloWorld?wsdl加入對方框中的wsdl欄中


點OK生成webservice soap ui調用的客戶端如下圖

它會生成11Binding和12Binding兩個客戶端,我們把11Binding的節點展開,雙擊Request 1,在右邊會顯示調用的soap樣例,在<hel:sayHello>?</hel:sayHello>塊中我們把問號替換成Monica,然后點上方“綠色”運行按鈕,我們就可以得到調用結果如下圖:

因此通過SOAP UI我們也可以測試我們的Web Service。

4.2?非阻塞式HelloWorldWithReturnNonBlock.java

與傳統的阻塞式webservice調用不同的是,一旦調用"serviceClient.sendReceive(payload);",客戶端將會被阻塞直到操作完成。這種方式在有很多Web Service需要在一個單一的客戶端應用程序中啟動時很不可取。一種解決方法是使用Non-Blocking API來調用這些Web Services。Axis2提供給用戶一種基于回叫機制的non-blocking API。

很多網上使用的“回調”接口都只能在Axis21.3中才能使用,而在Axis21.4中回調接口已經被升級成一個抽象類叫AxisCallBack類了,因此90%目前網上的關于“非阻塞式”的客戶端的代碼在Axis2中都是跑不起來的,在eclipse ide中會顯示“該類/方法已經被deprecated(廢棄)”。

因此請注意看筆者的代碼,先聲明一個用于非阻塞調用的回調(callback)類

HelloWorldNonBlockCB.java

package org.sky.axis2.helloworld;

import java.util.Iterator;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMElement;

import org.apache.axiom.om.OMNode;

import org.apache.axis2.client.async.AxisCallback;

import org.apache.axis2.context.MessageContext;

import org.apache.axis2.databinding.utils.BeanUtil;

import org.apache.axis2.engine.DefaultObjectSupplier;

public class HelloWorldNonBlockCB implements AxisCallback {

???????? private boolean complete = false;

???????? public void onMessage(MessageContext msgContext) {

?????????????????? System.out.println(msgContext.getEnvelope().getBody());

?????????????????? OMElement element = msgContext.getEnvelope().getBody()

???????????????????????????????????? .getFirstElement();

?????????????????? OMElement result = element.getFirstChildWithName(new QName(

???????????????????????????????????? "http://helloworld.axis2.sky.org", "name"));

?????????????????? System.out.println(result.getText());

?????????????????? synchronized (this) {

??????????????????????????? this.notify();

?????????????????? }

???????? }

???????? public boolean isComplete() {

?????????????????? return complete;

???????? }

???????? public void onFault(MessageContext msgContext) {

?????????????????? System.out.println(msgContext.getEnvelope().getBody().getFault()

???????????????????????????????????? .toString());

?????????????????? synchronized (this) {

??????????????????????????? this.notify();

?????????????????? }

???????? }

???????? public void onError(Exception e) {

?????????????????? e.printStackTrace();

?????????????????? synchronized (this) {

??????????????????????????? this.notify();

?????????????????? }

???????? }

???????? public void onComplete() {

?????????????????? this.complete = true;

?????????????????? synchronized (this) {

??????????????????????????? this.notify();

?????????????????? }

???????? }

}

有了callback接口,我們來寫我們的webservice調用類

HelloWorldWithReturnNonBlock.java

package org.sky.axis2.helloworld;

import org.apache.axis2.addressing.EndpointReference;

import org.apache.axiom.om.OMAbstractFactory;

import org.apache.axiom.om.OMElement;

import org.apache.axiom.om.OMFactory;

import org.apache.axiom.om.OMNamespace;

import org.apache.axis2.AxisFault;

import org.apache.axis2.addressing.EndpointReference;

import org.apache.axis2.client.Options;

import org.apache.axis2.client.ServiceClient;

import org.apache.axis2.client.async.AxisCallback;

import org.apache.axis2.context.MessageContext;

public class HelloWorldWithReturnNonBlock {

???????? private static EndpointReference targetEPR = new EndpointReference(

??????????????????????????? "http://localhost:8080/Axis2Service/services/HelloWorld");

???????? public void sayHello() {

?????????????????? OMFactory fac = OMAbstractFactory.getOMFactory();

?????????????????? OMNamespace omNs = fac.createOMNamespace(

???????????????????????????????????? "http://helloworld.axis2.sky.org", "");

?????????????????? OMElement method = fac.createOMElement("sayHello", omNs);

?????????????????? OMElement name = fac.createOMElement("name", omNs);

?????????????????? name.setText("ymk");

?????????????????? method.addChild(name);

?????????????????? method.build();

?????????????????? Options options = new Options();

?????????????????? options.setTo(targetEPR);

?????????????????? ServiceClient sender = null;

?????????????????? try {

????????????????????????????HelloWorldNonBlockCB callback = new HelloWorldNonBlockCB();

????????????????????????????sender = new ServiceClient();

????????????????????????????sender.setOptions(options);

????????????????????????????sender.sendReceiveNonBlocking(method, callback);

????????????????????????????synchronized (callback) {

?????????????????????????????????????try {

??????????????????????????????????????????????callback.wait();

?????????????????????????????????????} catch (InterruptedException e) {

??????????????????????????????????????????????e.printStackTrace();

?????????????????????????????????????}

????????????????????????????}

?????????????????? } catch (AxisFault e) {

??????????????????????????? e.printStackTrace();

?????????????????? } finally {

??????????????????????????? if (sender != null)

???????????????????????????????????? try {

?????????????????????????????????????????????? sender.cleanup();

???????????????????????????????????? } catch (Exception e) {

???????????????????????????????????? }

?????????????????? }

???????? }

???????? public static void main(String[] args) {

?????????????????? HelloWorldWithReturnNonBlock testClient = new HelloWorldWithReturnNonBlock();

?????????????????? testClient.sayHello();

???????? }

}

注意加粗標紅處的代碼。

4.3?非阻塞式雙工HelloWorldWithReturnDualNonBlock.java

非阻塞式的Web Service客戶端代碼很簡單,在此不做任何擅述,我們就說終極的非阻塞式雙工模式的Web Service客戶端使用Axis2的API如何實現。

記住以下幾個口決:

ü?? options.setUseSeparateListener(true);

非阻塞式雙工模式,會在客戶端也打開一個監聽器,而且一直不斷的監聽著服務器的返回值,該進程一旦被吊用,會一直被掛在客戶端這邊。

ü?? 設置webservice客戶端模式為雙工全開

options.setTransportInProtocol(Constants.TRANSPORT_HTTP);

ü?? 先尋址,后engageModule

在雙工模式下Web Service的客戶端需要尋址,即engageModule,這個engageModule需要這樣的一個參數:

engageModule(“addressing”)

或者也可寫成:

engageModule(Constants.MODULE_ADDRESSING);
這個engageModule就是需要訪問你的工程的WEB-INF\modules\目錄下的一個叫addressing-1.4.mar的文件。

因此在調用engageModule語句之間有兩種方式來調用你的WEB-INF\modules目錄下的addressing-1.4.mar文件。

第一種方式:

ConfigurationContext sysContext = ConfigurationContextFactory

?????????????????????????????????????? .createConfigurationContextFromFileSystem(

???????????????????????????????????????????????????????? "D:\\wspace\\Axis2Service\\WebContent\\WEB-INF",

???????????????????????????????????????????????????????? null);

????????????????????sender = new ServiceClient(sysContext, null);

??????????????????????????? sender.engageModule(Constants.MODULE_ADDRESSING);

第二種方式:

sender = new ServiceClient(sysContext, null);

???????? sender.engageModule(Constants.MODULE_ADDRESSING);

在第二種方式中,不需要為new ServiceClient()指定第一個sysContext參數,但是,你必須把WEB-INF\modules\addressing-1.4.mar指定到你的工程的classpath中去,如下圖

要不然運行時會拋出下面這個exception:

org.apache.axis2.AxisFault:Unable to engage module : addressing

下面來看代碼,此處的callback我們延用4.2小節中建立的callback接口即可,此處不再重復,直接給出客戶端代碼:

package org.sky.axis2.helloworld;

import org.apache.axiom.om.OMAbstractFactory;

import org.apache.axiom.om.OMElement;

import org.apache.axiom.om.OMFactory;

import org.apache.axiom.om.OMNamespace;

import org.apache.axis2.AxisFault;

import org.apache.axis2.Constants;

import org.apache.axis2.addressing.EndpointReference;

import org.apache.axis2.client.Options;

import org.apache.axis2.client.ServiceClient;

import org.apache.axis2.context.ConfigurationContext;

import org.apache.axis2.context.ConfigurationContextFactory;

public class HelloWorldWithReturnDualNonBlock {

private static EndpointReference targetEPR = new EndpointReference(

??????????????????? "http://localhost:8080/Axis2Service/services/HelloWorld");

public static boolean finish = false;

public void sayHello() {

?????????? OMFactory fac = OMAbstractFactory.getOMFactory();

?????????? OMNamespace omNs = fac.createOMNamespace(

???????????????????????????? "http://helloworld.axis2.sky.org", "");

?????????? OMElement method = fac.createOMElement("sayHello", omNs);

?????????? OMElement name = fac.createOMElement("name", omNs);

?????????? name.setText("ymk");

?????????? method.addChild(name);

?????????? method.build();

?????????? Options options = new Options();

?????????? options.setTo(targetEPR);

???????????options.setTransportInProtocol(Constants.TRANSPORT_HTTP);

???????????options.setUseSeparateListener(true);

?????????? options.setAction("urn:sayHello");

?????????? ServiceClient sender = null;

?????????? HelloWorldNonBlockCB callback = new HelloWorldNonBlockCB();

?????????? try {

??????????????????? sender = new ServiceClient();

????????????????????sender.engageModule(Constants.MODULE_ADDRESSING);

????????????????????sender.setOptions(options);

????????????????????sender.sendReceiveNonBlocking(method, callback);

????????????????????synchronized (callback) {

?????????????????????????????try {

???????????????????????????????????????callback.wait();

?????????????????????????????} catch (InterruptedException e) {

???????????????????????????????????????e.printStackTrace();

?????????????????????????????}

????????????????????}

?????????? } catch (Exception e) {

??????????????????? e.printStackTrace();

?????????? } finally {

??????????????????? try {

???????????????????????????? sender.cleanup();

??????????????????? } catch (Exception e) {

??????????????????? }

?????????? }

}

public static void main(String[] args) {

?????????? HelloWorldWithReturnDualNonBlock testClient = new HelloWorldWithReturnDualNonBlock();

?????????? testClient.sayHello();

}

}

4.4 運行雙工異步客戶端前的準備工作

將Axis2的安裝目錄下的conf目錄下(如我的是:D:\opensource\axis\axis2-1.4.1-bin\axis2-1.4.1\conf)的axis2.xml拷貝到你的工程的WEB-INF目錄下。

并確保這個axis2.xml里有如下語句:

<moduleref="addressing"/>


運行后顯示:

Axis2的雙工非阻塞式客戶端調用成功!完成Axis2編寫Web Service的第一天教程。

總結

以上是生活随笔為你收集整理的通向架构师的道路(第十天)之Axis2 Web Service(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。