1. 程式人生 > >淺淡Webservice、WSDL三種服務訪問的方式(附案例)

淺淡Webservice、WSDL三種服務訪問的方式(附案例)

http://www.cnblogs.com/yongfeng/archive/2013/01/30/2883146.html

Webservice

Webservice是使應用程式以與平臺和程式語言無關的方式進行相互通訊技術。

eg:站點提供訪問的資料介面:新浪微博、淘寶。

官方解釋:它是一種構建應用程式的普遍模型,可以在任何支援網路通訊的作業系統中實施執行;它是一種新的web應用程式分支,是自包含、自描述、模組化的應用,可以釋出、定位、通過web呼叫。WebService是一個應用元件,它邏輯性的為其他應用程式提供資料與服務.各應用程式通過網路協議和規定的一些標準資料格式(Http,XML,Soap)來訪問WebService,通過WebService內部執行得到所需結果.Web Service可以執行從簡單的請求到複雜商務處理的任何功能。一旦部署以後,其他WebService應用程式可以發現並呼叫它部署的服務。

 

SOAP(Simple Object Access Protocol):簡單物件訪問協議是在分散或分散式的環境中交換資訊並執行遠端過程呼叫的輕量級協議,是一個基於XML的協議。使用SOAP,不用考慮任何特定的傳輸協議(最常用的還是HTTP協議),可以允許任何型別的物件或程式碼,在任何平臺上,以任何一種語言相互通訊。

WSDL:Web Services Description Language的縮寫,是一個用來描述Web服務和說明如何與Web服務通訊的XML語言。為使用者提供詳細的介面說明書。

Axis:Axis本質上就是一個SOAP引擎(Apache Axis is an implementation of the SAOP),提供建立服務名、客戶端和閘道器SOAP操作的基本框架。但是Axis並不完全是一個SOAP引擎,它還包括:

  • 是一個獨立的SOAP伺服器。
  • 是一個嵌入Servlet引擎(eg:Tomcat)的伺服器。
  • 支援WSDL。
  • 提供轉化WSDL為Java類的工具。
  • 提供例子程式。
  • 提供TCP/IP資料包監視工具。

Axis有四種Service styles,分別是:

  • RPC(Remote Procedure Call Protocol遠端訪問呼叫協議,部署時屬於預設選項)
  • Document
  • Wrapped
  • Message

WSDD(Web Service Deployment Descriptor):Web服務分佈描述,它定義了Web服務的介面,如服務名、提供的方法、方法的引數資訊。

UDDI(Universal Description,Discovery,and Integration):統一描述、發現和整合,用於集中存放和查詢WSDL描述檔案,起著目錄伺服器的作用。

 

WSDL元素

WSDL元素基於XML語法描述了與服務進行互動的基本元素:

Type(訊息型別):資料型別定義的容器,它使用某種型別系統(如XSD)。

Message(訊息):通訊資料的抽象型別化定義,它由一個或者多個part組成。

Part:訊息引數

Operation(操作):對服務所支援的操作進行抽象描述,WSDL定義了四種操作:

  • 單向(one-way):端點接受資訊;
  • 請求-響應(request-response):端點接受訊息,然後傳送相關訊息;
  • 要求-響應(solicit-response):端點發送訊息,然後接受相關訊息;
  • 通知(notification):端點發送訊息。

Port Type (埠型別):特定埠型別的具體協議和資料格式規範。

Binding:特定埠型別的具體協議和資料格式規範

Port :定義為繫結和網路地址組合的單個端點。

Service:相關埠的集合,包括其關聯的介面、操作、訊息等。

 

以上類圖表達了Service、Port、Binding、Operation、Message之間的依賴、關聯、聚合、合成、泛化、實現,這裡暫不多說,若感興趣,請參考該文章

WSDL虛擬碼

WSDL 文件是利用這些主要的元素來描述某個 web service 的:

元素 定義

web service 執行的操作

複製程式碼
<message> web service 使用的訊息
<types> web service 使用的資料型別
<binding> web service 使用的通訊協議
一個 WSDL 文件的主要結構是類似這樣的:
<definitions>
<types>
definition of types........
</types>
<message>
definition of a message....
</message>
<portType>
definition of a port.......
</portType>
<binding>
definition of a binding....
</binding>
</definitions>
複製程式碼

WSDL 文件可包含其它的元素,比如 extension 元素,以及一個 service 元素,此元素可把若干個 web services 的定義組合在一個單一的 WSDL 文件中

實踐

為了形成鮮明的對比,客戶端用CS架構來建立客戶端。

實踐之一:建立服務端

建立ASP.NET Web服務

 

程式碼示例

複製程式碼
using System;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;

using DotNet.Model;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允許使用 ASP.NET AJAX 從指令碼中呼叫此 Web 服務,請取消對下行的註釋。
// [System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService
{
    public Service () {
        //如果使用設計的元件,請取消註釋以下行
        //InitializeComponent();

    }
     [WebMethod(Description="獲取字串",MessageName="HelloWorld")]
    public string HelloWorld() {
        return "Hello World";
    }

    [WebMethod(Description="獲取使用者資訊",MessageName="getCustomer")]
    public Customer getCustomer(Customer cus1)
    {
        return cus1;
    }
 
    [WebMethod(Description = "獲取使用者資訊以引數形式", MessageName = "getCustomerFromParams")]
    public Customer getCustomerFromParams(int id, string name, string address)
    {
        Customer cus1 = new Customer();
        cus1.cus_id = id;
        cus1.cus_name = name;
        cus1.cus_address = address;
        return cus1;
    }
   
}
複製程式碼

實踐之二:建立客戶端

建立ASP.NET WEB客戶端(以CS架構)

 

程式碼示例

 (其中一種方式通過建立“服務引用”的方式,輸入“http://localhost:埠號/XX.asmx?wsdl”方式,獲得服務訪問介面)

複製程式碼
      private ServiceReference1.ServiceSoapClient myclient = new ServiceReference1.ServiceSoapClient();
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                /* 第一種方式可以傳參、傳實體,返回實體 */
                ServiceReference1.ServiceSoapClient myclient = new ServiceReference1.ServiceSoapClient();
                ServiceReference1.Customer tem = new ServiceReference1.Customer();
                tem.cus_id = int.Parse(textBox1.Text);
                tem.cus_name = textBox2.Text;
                tem.cus_address = textBox3.Text;
                string str = JsonHelper.Jso_ToJSON(myclient.getCustomer(tem));
                richTextBox1.Text = str;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = string.Empty;
            try
            {
                richTextBox1.Text = myclient.HelloWorld();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
 
        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                /* 第二種方式可以傳參,返回實體(不能傳入一個物件實體,但是配置動態靈活) */
                string url = "http://localhost:3199/ServicePort/Service.asmx";
                string methodname = "getCustomerFromParams";

                object[] obj = new object[3];
                obj[0] = int.Parse(textBox1.Text);
                obj[1] = textBox2.Text;
                obj[2] = textBox3.Text;
                string str = JsonHelper.Jso_ToJSON(WebServiceHelper.InvokeWebService(url, methodname, obj));
                richTextBox1.Text = str;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
 
        private void button5_Click(object sender, EventArgs e)
        {
            try
            {
                /* 第三種方式可以傳參、傳實體,返回XmlDom(配置動態靈活,響應處理麻煩了點而已) */
                string url = "http://localhost:3199/ServicePort/Service.asmx";
                string methodname = "getCustomer";
                Hashtable parm = new Hashtable();
                string objectName = "cus1";
                parm["cus_id"] = int.Parse(textBox1.Text);
                parm["cus_name"] = textBox2.Text;
                parm["cus_address"] = textBox3.Text;
                XmlDocument oo = WebServiceXmlHelper.QuerySoapWebServiceByObject(url, methodname, objectName, parm);
                richTextBox1.Text = oo.InnerXml;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
複製程式碼

執行效果

服務端

 

 

WSDL

 

客戶端(支援多平臺,如伺服器的Webservice用Java、.Net等)

第1種方式:傳參、傳實體,URL配置缺少靈活,資料處理靈活

 

第2種方式:傳參,不能傳實體,URL配置靈活, 資料處理要稍微加工

 

第3種方式:傳參、傳實體、URL配置靈活,資料處理要稍微加工

 

小結

  • 如果只傳遞引數,可以用HTTP來傳遞,Webservice提供的介面如下

HTTP POST

以下是 HTTP POST 請求和響應示例。所顯示的佔位符需替換為實際值。

複製程式碼
POST /ServicePort/Service.asmx/getCustomerFromParams HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: length
 
id=string&name=string&address=string
複製程式碼

返回接收串

複製程式碼
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<Customer xmlns="http://tempuri.org/">
  <cus_id>int</cus_id>
  <cus_name>string</cus_name>
  <cus_address>string</cus_address>
</Customer>
複製程式碼
  • 如果是傳遞實體或傳遞引數,也可以使用SOAP來傳遞,Webservice提供的介面如下
複製程式碼
POST /ServicePort/Service.asmx HTTP/1.1
Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
 
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getCustomerFromParams xmlns="http://tempuri.org/">
      <id>int</id>
      <name>string</name>
      <address>string</address>
    </getCustomerFromParams>
  </soap12:Body>
</soap12:Envelope>
複製程式碼

返回接收串:

複製程式碼
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getCustomerFromParamsResponse xmlns="http://tempuri.org/">
      <getCustomerFromParamsResult>
        <cus_id>int</cus_id>
        <cus_name>string</cus_name>
        <cus_address>string</cus_address>
      </getCustomerFromParamsResult>
    </getCustomerFromParamsResponse>
  </soap12:Body>
</soap12:Envelope>
複製程式碼

 WebService向外釋出介面的功能,能夠更好的為其它平臺提供資料以及現實資訊平臺一體化。