天天看點

WebService深入淺出(轉)

WebService深入淺出

什麼是Webservice

W3C組織對其的定義如下,它是一個軟體系統,為了支援跨網絡的機器間互相操作互動而設計。Web Service服務通常被定義為一組子產品化的API,它們可以通過網絡進行調用,來執行遠端系統的請求服務。
           
簡單的說:WebService即Web服務,它是一種跨程式設計語言和跨作業系統平台的遠端調用技術。
           
Web服務:基于HTTP和XML的技術,HTTP是網際網路上應用最為廣泛的一種網絡協定,而XML是跨平台的基礎。
跨程式設計語言和跨操作平台:就是說服務端程式采用java編寫,用戶端程式則可以采用其他程式設計語言編寫,反之亦然!跨作業系統平台則是指服務端程式和用戶端程式可以在不同的作業系統上運作。
遠端調用:就是一台計算機a上的一個程式可以調用到另外一台計算機b上的一個對象的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉賬調用的轉賬方法的代碼其實是跑在銀行伺服器上。再比如,amazon,天氣預報系統,淘寶網,校内網,百度等把自己的系統服務以webservice服務的形式暴露出來,讓第三方網站和程式可以調用這些服務功能,這樣擴充了自己系統的市場占有率
           
web Service:有兩大類:
一類:傳統的webservice,大web service,相對複雜。
一類:輕量級的webservice
           

WebService三要素

WebService的三要素是:
    SOAP (Simple Object Access Protocol):簡易對象通路協定,soap用來描述傳遞資訊的格式。
    WSDL (WebServices Description Language):Web服務描述語言,用來描述如何通路具體的接口。
    UDDI (Universal Description Discovery and Integration):通用描述、發現及整合,用來管理、分發、查詢webService。
           

原生态WebService用戶端編寫 

常見的手機歸屬地查詢? 

http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl 

1.打開cmd,執行wsimport生成代碼。

你不懂指令為什麼能生成代碼不要緊,記住就好!這是JDK/BIN目錄下自帶的
           
  • 1
WebService深入淺出(轉)

2.如圖所示,代碼生成在D:\MyTest\webservice。會生成class和java檔案。删除class檔案 

WebService深入淺出(轉)

3.開始編寫查詢手機号歸屬地用戶端 

eclipse建立工程,将生成的代碼copy到你自己想要的包下。記得修改package導包 

然後編寫第一個WebService用戶端接口

package com.ssm.remote.webservice.client;

import com.ssm.remote.webservice.MobileCodeWS;
import com.ssm.remote.webservice.MobileCodeWSSoap;

/**
 * 第一個WebService用戶端示範
 * 根據手機号查詢手機歸屬地
 * http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
 * @author dongyang
 * 
 *  WebService的三要素是:(面試)
 *     SOAP (Simple Object Access Protocol):簡易對象通路協定,soap用來描述傳遞資訊的格式。
 *     WSDL (WebServices Description Language):Web服務描述語言,用來描述如何通路具體的接口。
 *     UDDI (Universal Description Discovery and Integration):通用描述、發現及整合,用來管理、分發、查詢webService。
 *
 */

public class PhoneAddressClient {

    public static void main(String[] args) {
        System.out.println(getPhoneAddress("15000814726"));
    }

    public static String getPhoneAddress(String phone){
        //1.執行個體化生成的服務類
        MobileCodeWS ws = new MobileCodeWS();
        //2.調用服務類的方法擷取接口執行個體
        MobileCodeWSSoap soap = ws.getMobileCodeWSSoap();
        //3.通過接口直接擷取資料
        return soap.getMobileCodeInfo(phone,"");
    }
}
           
WebService深入淺出(轉)
這就是原生态的WebServiceke用戶端接口。
簡單熟悉這個例子之後。下面開始自定義服務端,釋出服務,編寫用戶端
           

自定義WebService服務端并釋出服務編寫用戶端測試 

1.編寫服務接口

package com.ssm.remote.webservice.server;

/**
 * WebService服務端
 * @author dongyang
 *
 */
public interface FisrtWebService {

    String getAddressByPhoneNo(String phoneNo);
}
           

2.編寫接口實作類

package com.ssm.remote.webservice.server.impl;

import javax.jws.WebService;

import com.ssm.remote.webservice.server.FisrtWebService;

@WebService//加上這個注解,表示此實作類就是WebService服務
public class FisrtWebServiceImpl implements FisrtWebService {

    public String getAddressByPhoneNo(String phoneNo) {
        return phoneNo + ": 歸屬地是上海";
    }

}
           

3.釋出服務

package com.ssm.remote.webservice.server;

import javax.xml.ws.Endpoint;

import com.ssm.remote.webservice.server.impl.FisrtWebServiceImpl;

/**
 * 釋出服務
 * @author dongyang
 *
 */
public class PublishServerTest {

    public static void main(String[] args) {
        //參數1:服務被通路的url   ip+端口号+服務名
        //參數2:實作類
        Endpoint.publish("http://localhost:9999/getAddress", new FisrtWebServiceImpl());
        System.out.println("服務釋出成功");

        //檢視WebService服務是否啟動  url+?wsdl
        //http://localhost:9999/getAddress?wsdl是否能顯示

    }
}
           

4.驗證服務是否釋出成功 

通路釋出服務的ip+端口+服務名+?wsdl 

http://localhost:9999/getAddress?wsdl是否能顯示 

WebService深入淺出(轉)

5.照第一個例子那樣通過指令生成代碼,編寫用戶端代碼。這裡教大家生成代碼自定義包名并将class檔案和java檔案分開 

WebService深入淺出(轉)
類似于那種原生态的用戶端,就不重複了,下面編寫一個優化的用戶端。
還是老樣子,把生成的代碼copy過來。

特别注意,用戶端的FisrtWebServiceImpl是接口,不是服務端編寫的實作類
           
package com.ssm.remote.webservice.client;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

/**
 * 自定義WebService服務端的用戶端調用示範
 * @author dongyang
 *
 */
public class FisrtClinet {

    public static void main(String[] args) throws MalformedURLException {

        //TODO 也可以按照入門案例PhoneAddressClient那樣調用,但是這樣是不是更好呢?更具靈活性

        //FisrtWebServiceImplService是自動生成的接口,不是服務端的實作類
        Service service = Service.create(new URL("http://localhost:9999/getAddress?wsdl")
                , new QName("http://impl.server.webservice.remote.ssm.com/","FisrtWebServiceImplService"));
        FisrtWebServiceImpl impl = service.getPort(FisrtWebServiceImpl.class);
        System.out.println(impl.getAddressByPhoneNo("15000815726"));
    }

}
           
WebService深入淺出(轉)

wsdl的基本結構 

舉我們自定義的服務的wsdl:

<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://impl.server.webservice.remote.ssm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.server.webservice.remote.ssm.com/" name="FisrtWebServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://impl.server.webservice.remote.ssm.com/" schemaLocation="http://localhost:9999/getAddress?xsd=1"/>
</xsd:schema>
</types>
<message name="getAddressByPhoneNo">
<part name="parameters" element="tns:getAddressByPhoneNo"/>
</message>
<message name="getAddressByPhoneNoResponse">
<part name="parameters" element="tns:getAddressByPhoneNoResponse"/>
</message>
<portType name="FisrtWebServiceImpl">
<operation name="getAddressByPhoneNo">
<input wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoRequest" message="tns:getAddressByPhoneNo"/>
<output wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoResponse" message="tns:getAddressByPhoneNoResponse"/>
</operation>
</portType>
<binding name="FisrtWebServiceImplPortBinding" type="tns:FisrtWebServiceImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="getAddressByPhoneNo">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="FisrtWebServiceImplService">
<port name="FisrtWebServiceImplPort" binding="tns:FisrtWebServiceImplPortBinding">
<soap:address location="http://localhost:9999/getAddress"/>
</port>
</service>
</definitions>
           
WebService深入淺出(轉)

離線解析

場景:你開發用戶端的時候,不能和服務端網絡連接配接。但程式還要開發,通過分析發現,用戶端開發主要有wsdl的文檔就可以了。因為有該文檔,就可以生成樁(用戶端代碼)。
是以我們可以将wsdl儲存下來,儲存成xml。在不能通路服務端的情況下使用。
           
  • 1
  • 2
WebService深入淺出(轉)
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://impl.server.webservice.remote.ssm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.server.webservice.remote.ssm.com/" name="FisrtWebServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://impl.server.webservice.remote.ssm.com/" schemaLocation="http://localhost:9999/getAddress?xsd=1"/>
</xsd:schema>
</types>
<message name="getAddressByPhoneNo">
<part name="parameters" element="tns:getAddressByPhoneNo"/>
</message>
<message name="getAddressByPhoneNoResponse">
<part name="parameters" element="tns:getAddressByPhoneNoResponse"/>
</message>
<portType name="FisrtWebServiceImpl">
<operation name="getAddressByPhoneNo">
<input wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoRequest" message="tns:getAddressByPhoneNo"/>
<output wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoResponse" message="tns:getAddressByPhoneNoResponse"/>
</operation>
</portType>
<binding name="FisrtWebServiceImplPortBinding" type="tns:FisrtWebServiceImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="getAddressByPhoneNo">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="FisrtWebServiceImplService">
<port name="FisrtWebServiceImplPort" binding="tns:FisrtWebServiceImplPortBinding">
<soap:address location="http://localhost:9999/getAddress"/>
</port>
</service>
</definitions>
           

SOAP協定

SOAP,Simple Object Access Protocol,簡單對象通路協定,簡單的說就是用于通路網絡服務的協定;它是基于 XML 的簡易協定,可使應用程式在 HTTP 之上進行資訊交換。

SOAP是一種網絡通信協定,用于網絡上、不同平台、不同語言的應用程式間的通訊。
WebService通過HTTP協定發送請求和接收結果時,發送的請求内容和結果内容都采用XML格式封裝,并增加了一些特定的HTTP消息頭,以說明HTTP消息的内容格式,這些特定的HTTP消息頭和XML内容格式就是SOAP協定。SOAP提供了标準的RPC方法來調用Web Service。
  SOAP協定 = HTTP協定 + XML資料格式。
  SOAP協定定義了SOAP消息的格式,SOAP協定是基于HTTP協定的,SOAP也是基于XML和XSD的,XML是SOAP的資料編碼方式。
SOAP很就簡單并可擴充支援面向對象,允許跨防火牆。
SOAP被作為 W3C 标準來發展。
SOAP現行兩個版本:1.1和1.2。
           

SOAP、HTTP、TCP/IP之間的關系 

WebService深入淺出(轉)

SOAP協定分為1.1和1.2兩個版本

為了相容性,大部分程式員都會優先使用1.1
           

SOAP消息的标準格式 

WebService深入淺出(轉)

SOAP1.1和SOAP1.2協定的異同

SOAP1.1和1.2版本之間的大部分差異通常也是可以忽略的
SOAP1.1隻可以綁定到HTTP協定,而SOAP1.2除了HTTP協定之外還支援SMTP綁定。在JAX-WS中,類似于大多數架構,SOAP1.1作為預設實作,盡管如此在JAX-WS中可以随時采用SOAP1.2。
           
應用的價值:
1.  盡量使用同版本的來互相調用,原因,相容性好,性能高。
2.  如果服務端使用1。1,那麼用戶端隻能使用1。1,但服務端使用1。2,那麼用戶端可以使用1。1或1。2。,優先用1。2。但國内,很多用戶端的開發為了适應不同版本的服務端,會用1。1來開發。
           

用jax-ws開發的用戶端會自動适應服務端的版本。

性能壓力測試

我們自己編寫的服務端,肯定需要自己測試,行不行。性能如何?
部落客推薦SoapUI5.2.1。當然你可以下載下傳其餘軟體或者其餘版本
           
WebService深入淺出(轉)
WebService深入淺出(轉)

CXF架構和Spring的內建開發包括hessian的開發請留意續集