wsdl詳解


<wsdl:definitions 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ns1
="http://org.apache.axis2/xsd"
xmlns:ns
="http://impl.service.utcs.ctc"
xmlns:wsaw
="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:http
="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:ax21
="http://beans.service.utcs.ctc/xsd"
xmlns:xs
="http://www.w3.org/2001/XMLSchema"
xmlns:mime
="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap
="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12
="http://schemas.xmlsoap.org/wsdl/soap12/"
targetNamespace
="http://impl.service.utcs.ctc"> <wsdl:documentation>UtcsClient</wsdl:documentation>
 Types 是一個數據類型定義的容器。Element元素定義在消息(message)定義中需要的XML元素的類型定義。complexType 元素定義了XML元素由哪些具體的類型組成以及組成元素的順序。 complexType元素如果放在Types元素下面而又不被element元素包含,那么它就定義了一個公用的數據類型。可以被多個element元素所引用 <wsdl:types> <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://beans.service.utcs.ctc/xsd"> <xs:complexType name="CrossControlMode"> <!- 定義一個 CrossControlMode類 這個類有三個屬性crossID,value,sHeadPackage -> <xs:sequence> <xs:element minOccurs="0" name="crossID" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="value" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="sHeadPackage" nillable="true" type="ax21:HeadPackage"/> </xs:sequence> </xs:complexType> <xs:complexType name="HeadPackage"> <xs:sequence> <xs:element minOccurs="0" name="from" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="seq" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="to" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="token" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="version" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="CrossCycle"> <xs:sequence> <xs:element minOccurs="0" name="crossID" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="lastCycleLen" type="xs:short"/> <xs:element minOccurs="0" name="startTime" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="sHeadPackage" nillable="true" type="ax21:HeadPackage"/> </xs:sequence> </xs:complexType> <xs:complexType name="CrossParam"> <xs:sequence> <xs:element minOccurs="0" name="crossID" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="crossName" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="detID" nillable="true" type="xs:string"/> <xs:element maxOccurs="unbounded" minOccurs="0" name="detIDList" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="feature" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="isKey" type="xs:short"/> <xs:element maxOccurs="unbounded" minOccurs="0" name="laneNoList" nillable="true" type="xs:short"/> <xs:element maxOccurs="unbounded" minOccurs="0" name="phaseNoList" nillable="true" type="xs:short"/> <xs:element maxOccurs="unbounded" minOccurs="0" name="planNoList" nillable="true" type="xs:short"/> <xs:element maxOccurs="unbounded" minOccurs="0" name="stageNoList" nillable="true" type="xs:short"/> <xs:element minOccurs="0" name="sHeadPackage" nillable="true" type="ax21:HeadPackage"/> </xs:sequence> </xs:complexType>
WSDL: Web 服務描述語言(Web Services Descirption Language).

a. 服務提供者是通過web服務描述將所有用於調用Web服務的規范傳送給服務請求者的。
b. WSDL是通過標准的XML格式來描述Web服務。
c. 它用一種與實現語言無關的抽象方式定義了web服務的操作和消息。
d. 操作和消息被抽象描述,然后綁定到具體的網絡協議和端點。
e. web服務包含了一組抽象的端點。

WSDL概念模型:
1. 服務做些什么: 服務所提供的操作(方法)。 對應porttype,operation元素。
2. 如何訪問服務: 數據格式詳情(types,message)及訪問服務操作的必要協議(Binding)。
3. 服務位於何處: 由特定協議約定的網絡地址。如URL。 (service,port)。

WSDL的組成元素
1.  Types 是一個數據類型定義的容器。Element元素定義在消息(message)定義中需要的XML元素的類型定義。complexType 元素定義了XML元素由哪些具體的類型組成以及組成元素的順序。 complexType元素如果放在Types元素下面而又不被element元素包含,那么它就定義了一個公用的數據類型。可以被多個element元素所引用。

例如: 
<wsdl:types>
  <xsd:schema
    targetNamespace=""
    xmlns=""
    xmlns:wsdl=""
    elementFormDefault="qualified">
    <xsd:complexType name="Transaction">
    <xsd:sequence>
     <xsd:element minOccurs="1" maxOccurs="1"
            name="number" type="xsd:int" />
     <xsd:element minOccurs="0" maxOccurs="1"
            name="checknumber" type="xsd:int" />
     <xsd:element minOccurs="1" maxOccurs="1"
            name="date" type="xsd:date" />
     <xsd:element minOccurs="1" maxOccurs="1"
            name="header" type="xsd:string" />
     <xsd:element minOccurs="1" maxOccurs="1"
            name="amount" type="xsd:float" />
    </xsd:sequence>
   </xsd:complexType>
  這是一個復雜類型的定義,這個有點像定義了一個叫做Transaction的類,而這個類有屬性number,checknumber,date,header和amount。這里定義了一個公用的數據類型結構。
  <xsd:element name="LookupTransactionsResponse">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element minOccurs="0" maxOccurs="unbounded"
             name="transactions" type="xsd1:Transaction" />
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>

這里定義了一個數據類型元素(element)叫做LookupTransactionsResponse,在這里引用了前面定義的Transaction的集合. 在后面的消息定義中將會引用到這里所定義的數據類型元素。

   <xsd:element name="LookupTransactions">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element minOccurs="1" maxOccurs="1"
             name="accountNumber" type="xsd:int" />
      <xsd:element minOccurs="0" maxOccurs="1"
             name="date1" type="xsd:date" />
      <xsd:element minOccurs="0" maxOccurs="1"
             name="date2" type="xsd:date" />
      <xsd:element minOccurs="1" maxOccurs="1"
             name="token" type="xsd:base64Binary" />
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>

這里定義的數據類型是一個參數列表,它有accountNumber,date1,date2,token組成。類似於 SomeObject.lookupTransactions(accountNumber,date1,date2,token) 里面的參數列表。complexType 定義在了element里面,那么這個數據類型結構只能是LookupTransactions 私有的了。
  </xsd:schema>
</wsdl:types>

2.  Message具體定義了在通信中使用的消息的數據結構。什么叫通信中使用?因為WSDL是給調用服務的人看的。那我要調用你的服務,我的soap請求消息應該怎么寫呢,格式是什么呢?這里就給出定義了。
  <wsdl:message name="LookupTransactionsResponse">
    <wsdl:part name="parameters" element="xsd1:LookupTransactionsResponse" />
   </wsdl:message>

  這里定義了服務在調用之后消息返回的數據格式。其名字為parameters,數據的類型就是xsd1:LookupTransactionsResponse。
  <wsdl:message name="LookupTransactions">
    <wsdl:part name="parameters" element="xsd1:LookupTransactions" />
   </wsdl:message>

這里定義了訪問服務時需要傳什么樣的數據。
  3.  PortType 具體定義了一個服務可以訪問的接口。是對於某個端口類型所支持操作的抽象集合。其實就是說服務定義了多少個可以被調用的方法。
  這里面有兩層意思:第一,針對某個端口(porttype),如soap端口類型,http端口類型。端口可以包含任意數量的操作。第二,定義了服務所擁有的操作(operation)。

<wsdl:portType name="OnlineBankingPortType">
  <wsdl : peration name="LookupTransactions">
   <wsdl:input message="tns:LookupTransactions" />
   <wsdl : utput message="tns:LookupTransactionsResponse" />
  </wsdl : peration>
</wsdl:portType>
這里定義了一個可以訪問的方法LookupTransactions。這個方法的入參,又叫入站消息吧是message里面定義的tns:LookupTransactions。 同時這個方法還有一個返回對象,又叫出戰消息,是message里面所定義的tns:LookupTransactionsResponse
  <wsdl:portType name="ChinaStockWebServiceSoap">
     <wsdl : peration name="getStockImageByCode">
      <wsdl:documentation  
       xmlns:wsdl="">
        sdf
      </wsdl:documentation>    
      <wsdl:input message="tns:getStockImageByCodeSoapIn" />    
      <wsdl : utput message="tns:getStockImageByCodeSoapOut" /> 
     </wsdl : peration>
   </wsdl:portType>
  <wsdl:portType name="ChinaStockWebServiceHttpPost">
    <wsdl : peration name="getStockImageByCode">
     <wsdl:documentation xmlns:wsdl="">
      test
     </wsdl:documentation>
    <wsdl:input message="tns:getStockImageByCodeHttpPostIn" />
    <wsdl : utput message="tns:getStockImageByCodeHttpPostOut" />
    </wsdl : peration>
   </wsdl:portType>    

這個例子就定義了兩個端口類型soap和httppost。
  Types,Message和PortType抽象地描述了是如何調用webservice的,與具體的web服務部署無關。注意這里全部用的是wsdl的命名空間。沒有用到soap的命名空間。在后面的綁定和部署就會用到soap消息的命名空間了。

4. Binding 定義了某個PortType與某個具體的網絡傳輸協議或是消息傳輸協議的綁定。

<wsdl:binding name="OnlineBankingPortBinding"
        type="tns:OnlineBankingPortType">
  <soap:binding transport=""
         />
  <wsdl : peration name="LookupTransactions">
   <soap : peration soapAction=""
           />
    <wsdl:input>
     <soap:body use="literal" />
    </wsdl:input>
    <wsdl : utput>
     <soap:body use="literal" />
    </wsdl : utput>
  </wsdl : peration>
</wsdl:binding>

前面所定義的端口類型OnlineBankingPortType 綁定在 soap/http協議上面了。這里用到soap的命名空間進行了綁定。
Soap:binding :指出綁定是針對soap協議格式的。Transport指定了傳輸協議。Style指定通信風格。有“rpc”和“document”兩種風格。
Soap : peration :為SOAP服務操作提供消息。通常可以指明此操作的SOAPActionHTTP頭。
Soap:body :指出消息如何在SOAP BODY元素中表現。
 
5.  Service 一個服務所有訪問入口的部署細節。一個Service往往包含多個訪問入口(如URL),每個訪問入口都會使用一個port來描述。
6.  Port 描述一個服務訪問入口的部署細節。由哪個web地址(URL)來訪問,綁定到什么樣的端口上面。
   <wsdl:service name="OnlineBankingService">
    <wsdl:port name="OnlineBankingPort" binding="tns:OnlineBankingPortBinding">
     <soap:address location="http://localhost:8080/axis2/services/OnlineBankingService" />
    </wsdl:port>
   </wsdl:service>

   Soap:address 為SOAP服務訪問指定的網絡地址。

  下面的例子就定義了多個訪問端口。
  <wsdl:service name="ChinaStockWebService">
  <wsdl:documentation xmlns:wsdl="">
   test
  </wsdl:documentation>
  <wsdl:port name="ChinaStockWebServiceSoap"
   binding="tns:ChinaStockWebServiceSoap">
   <soap:address
    location="" />
  </wsdl:port>
  <wsdl:port name="ChinaStockWebServiceSoap12"
   binding="tns:ChinaStockWebServiceSoap12">
   <soap12:address
    location="" />
  </wsdl:port>
  <wsdl:port name="ChinaStockWebServiceHttpGet"
   binding="tns:ChinaStockWebServiceHttpGet">
   <http:address
    location="" />
  </wsdl:port>
  <wsdl:port name="ChinaStockWebServiceHttpPost"
   binding="tns:ChinaStockWebServiceHttpPost">
   <http:address
    location="" />
  </wsdl:port>
</wsdl:service>
  客戶端測試代碼:
public class OnlineBankAXIOMClient {
  private static EndpointReference targetEPR =
    new EndpointReference(
               "http://localhost:8088/ums/services/OnlineBankingService");
  public static OMElement getLoginPayload(String usernamestr,String passswordstr) {
    OMFactory fac = OMAbstractFactory.getOMFactory();
    
    //命名空間必須是,
    //而不是
    //因為這里是定義消息格式的命名空間。在Types元素里面的定義是
    //<wsdl:types>
    //<xsd:schema
    //targetNamespace=""
    //.......
    //所以數據類型的定義的命名空間就是""
    OMNamespace omNs = fac.createOMNamespace(
                         "", "tns");
    OMElement method = fac.createOMElement("login", omNs);
    OMElement username = fac.createOMElement("username", omNs);
    username.addChild(fac.createOMText(username, usernamestr));
    method.addChild(username);
    
    OMElement password = fac.createOMElement("password", omNs);
    password.addChild(fac.createOMText(password, passswordstr));
    method.addChild(password);
    
    return method;
  }
  
  public static void main(String[] args) {
    try {
      OMElement payload = getLoginPayload("dragon","123");
      Options options = new Options();
      options.setTo(targetEPR);
      
      //這里必須配置SOAPAction=;
      //否則就會報“org.apache.axis2.AxisFault:
      //The endpoint reference (EPR) for the Operation not found is
      //http://localhost:8088/ums/services/OnlineBankingService and the WSA Action = urn:anonOutInOp”
      //的錯誤.
      //而且必須跟WSDL里面定義的一致
      //<wsdl : peration name="Login">
      //<soap : peration soapAction=""
      ///     />

      options.setAction("");
      options.setExceptionToBeThrownOnSOAPFault(true);
      options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
  ServiceClient sender = new ServiceClient();
      sender.setOptions(options);

      OMElement result = sender.sendReceive(payload);
  String response = result.getFirstElement().getText();
      System.out.println("if login is valid: " + response);
  } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
小結:
1. 想要很好地運用AXIOM寫客戶端程序,必須要充分熟悉WSDL規范的定義。
2. 注意命名空間。
3. 采用自底向上的實現(code-->WSDL)方法雖然開發輕松,但是很多知識點會弄不清楚。
采用自頂向下的實現(WSDL-->code)方法可控性更強,可以更好地掌握知識點。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM