soap开始使用肥皂


备注

本节概述了soap是什么,以及开发人员为什么要使用它。

它还应该提到肥皂中的任何大型主题,并链接到相关主题。由于soap的文档是新的,您可能需要创建这些相关主题的初始版本。

版本

发布日期
1.1 2000年5月8日
1.2 2003-06-24

使用JAX-WS创建简单的Web服务和客户端(文档/文字)

这是项目目录。

项目目录

  1. 服务端点接口

首先,我们将创建一个服务端点接口。 javax.jws.WebService @WebService 批注将类定义为Web服务端点。


import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;

// Service Interface with customize targetNamespace
@WebService(targetNamespace = "http://hello-soap/ws")
@SOAPBinding(style = Style.DOCUMENT, use=Use.LITERAL) //optional
public interface HelloSoap {

    @WebMethod String getHelloSoap(String name);

}
 
  1. 服务端点实施(SEI)

接下来我们将创建服务端点实现。我们将通过将endpointInterface 元素添加到实现类中的@WebService 批注来创建显式接口。以下是一些规则集28.1.1 JAX-WS端点必须遵循的JAX-WS端点的要求。 getHelloSoap方法向客户端返回一个问候语,并将名称传递给它。


import javax.jws.WebService;

// Customized Service Implementation (portName,serviceName,targetNamespace are optional)

@WebService(portName = "HelloSoapPort", serviceName = "HelloSoapService",
endpointInterface = "com.wonderland.hellosoap.HelloSoap", targetNamespace = "http://hello-soap/ws")
public class HelloSoapImpl implements HelloSoap {

    @Override
    public String getHelloSoap(String name) {
        return "[JAX-WS] Hello : " + name;
    }

}
 
  1. Web服务端点发布者

import javax.xml.ws.Endpoint;

public class HelloSoapPublisher {

    public static void main(String[] args) {
        // creating web service endpoint publisher
        Endpoint.publish("http://localhost:9000/ws/hello-soap", new HelloSoapImpl());
    }

}
 
  1. 接下来的步骤,我们将运行HelloSoapPublisher.java 作为java应用程序。然后,我们将通过在Web浏览器中请求URL http://localhost:9000/ws/hello-soap?wsdl 来查看WSDL文件。
HTTP://本地主机:9000 / WS /你好皂WSDL

如果在Web浏览器上显示XML数据格式,那么我们就可以开始下一步了。

你好皂?WSDL

注意:
如果您收到某种错误消息,可能需要使用wsgen 工具生成必要的JAX-WS可移植工件。我们在这里没有涉及wsgen 工具。

  1. Web服务客户端

最后一步,我们将创建一个访问我们已发布服务的客户端。


import java.net.URL;

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

public class HelloSoapClient {

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

        // create wsdl url
        URL wsdlDocumentUrl = new URL("http://localhost:8000/ws/hello-soap?wsdl");
        QName helloSoapService = new QName("http://hello-soap/ws", "HelloSoapService");
        // create web service
        Service service = Service.create(wsdlDocumentUrl, helloSoapService);
        // get object of pointed service port
        HelloSoap helloSoap = service.getPort(HelloSoap.class);
        // testing request
        System.out.println(helloSoap.getHelloSoap("Soap "));

    }

}
 

输出: [JAX-WS] Hello : Soap

注意:我们的Web服务客户端中的端口号已更改为8000 。这里的原因是,我使用Eclipse IDE,内置TCP/IP monitor 工具来跟踪消息(更多信息: 如何在Eclipse IDE中跟踪SOAP消息 )。出于功能测试目的尝试SoapUI | SOAP和REST API的功能测试

一般信息

SOAP是简单对象访问协议Simple Object Access Protocol )的首字母缩写,它定义了一种协议,用于通过远程过程调用(RPC)与其他SOAP服务或客户端交换数据。它有两个版本:

SOAP 1.2废弃了SOAP 1.1,因此建议尽可能使用SOAP 1.2。

它通常建立在HTTP / S之上,很少在SMTP或FTP上构建,尽管它会根据协议支持它。尽管HTTP通常用作底层传输协议,但SOAP仅使用它的有限子集。对于发送请求,它几乎完全依赖HTTP的POST 操作。理论上,从1.2开始, GET 调用是可能的,尽管文档必须作为URI参数传递,因此可能超过大约3000个字符边界,这被大多数框架拒绝。此外,安全相关的设置通常在特殊的SOAP标头中定义。

虽然SOAP和REST被称为Web服务,但它们本质上是非常不同的。一些框架区分WS(用于基于SOAP的服务)和RS(用于基于REST的服务)。

下表简要概述了两种Web服务类型之间的差异。

方面肥皂休息
标准 SOAPWSDL 没有标准,只是一种建筑风格
资源寻址间接通过SOAP操作通过唯一资源标识符(URI)
错误处理 SOAP错误消息 HTTP错误响应代码和可选的响应主体
数据表示 XML HTTP中所有可用的编码
HTTP使用情况作为传输协议映射在HTTP方法上的资源操作(CRUD)(GET,POST,PUT,DELETE,...)
交易支持通过SOAP标头通过将事务建模为资源
有状态(SOAP操作是应用程序的一部分) 无国籍(独立请求)
服务发现 UDDI / WSDL 实际上没有; API的Start-URI应返回子API列表
方法在SOAP体内 HTTP方法
方法参数由WSDL中的XML模式定义通过URI中的HTTP标头或路径/查询或Matrix参数
国家转型很难确定不直接基于数据下一个URI调用
缓存支持缓存通常不需要, HTTP定义的简单

肥皂

SOAP请求由SOAP信封组成,该信封必须包含一个body元素,并且可以包含一个可选的header元素。 header元素用于将某些配置传递给服务,例如WS-Security可以定义消息是加密的,或者WS-Coordination / WS-Transaction可以定义消息必须在事务中执行。

一个简单的SOAP 1.2请求通过HTTP添加两个值可能如下所示:

POST /calculator HTTP/1.1
Host: http://example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 224

<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
 <env:Body>
  <m:AddValues xmlns:m="http://example.org/calculator">
   <m:FirstValue>1</m:FirstValue>
   <m:SecondValue>2</m:SecondValue>
  </m:AddValues>
 </env:Body>
</env:Envelope>
 

对上述示例请求的响应可能如下所示

HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 329

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
 <soap:Body xmlns:m="http://www.example.org/calculator">
  <m:AddValuesResponse>
   <m:Result>3</m:Result>
  </m:AddValuesResponse>
 </soap:Body>
</soap:Envelope>
 

上面的示例定义了一个请求,该请求使用两个参数调用AddValues 方法, FirstValue 设置为1SecondValue 设置为2 。该请求导致在远程SOAP服务器上执行此方法,该服务器计算了值3 作为结果,该值封装在单独的响应元素中,按照惯例,该元素通常是调用的方法名称加上尾随Response 字符串,因此任何人都是检查响应可以得出结论,这是前一个AddValue 方法调用的响应。

SOAP 1.1和1.2之间的差异

只要协议支持绑定框架,SOAP 1.2就允许其他传输协议,然后是HTTP。

SOAP 1.1基于XML 1.0,而1.2基于XML Infoset,它允许使用其他序列化程序将SOAP消息序列化,然后使用SOAP 1.1使用的默认XML 1.0序列化程序。这允许ie将消息序列化为二进制消息,从而防止消息的XML性质的一些开销。除此之外,可以通过数据绑定来确定所使用的底层协议的序列化机制。

通过定义比其前身更具体的处理模型,消除了许多解释的可能性,SOAP 1.2也促进了互操作性方面。 SOAP with Attachment API(SAAJ)允许对SOAP 1.1和1.2消息进行操作,它帮助许多框架实现者处理和创建消息。

W3C发布了SOAP 1.1和1.2之间主要变化的简短概述

Web服务互操作性

Web服务互操作性(也称为WS-I)是由一些知名企业(如IBM,Microsoft,Oracle和HP )管理的互操作性指南,仅举几例。这些指南建议在SOAP主体中仅使用一个单独的根元素,即使SOAP允许在主体内包含多个元素。

WS-I由

  • WS-I Basic Profile又名WSI-BP
  • WS-I基本安全配置文件
  • 简单的肥皂结合配置文件

WSI-BP提供4个不同版本v1.0(2004)v1.1(2006)v1.2(2010)v2.0(2010),并定义了核心Web服务规范(如SOAP,WSDL )的互操作性指南和UDDI。通过使用Web服务描述语言(WSDL),SOAP服务可以在与其他端点的内聚集中描述其支持的操作和方法。 WSI-BP利用WSDL定义一个较窄的集合,然后完整的WSDL或SOAP模式将定义,从而消除规范本身内部的一些歧义,从而提高端点之间的互操作性。

WSDL

为了公布可用的SOAP操作,它们的参数以及要调用给客户端的相应端点,使用另一个基于XML的文档,简称Web Services Description Language 或WSDL。

WSDL描述了服务端点,SOAP消息与操作的绑定,操作的接口以及它们对客户端的类型。与SOAP类似,WSDL有2个版本可供选择,它们的语法略有不同,尽管它们对客户端表达的语义几乎相同。

WSDL 1.1

WSDL 1.1描述包含servicebindingportTypemessage 部分。它可以进一步导入或定义WSDL文件中的模式,这可以从对应于上面显示的计算器示例的示例WSDL文件中看到:

<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"
                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:calc="http://example.org/calculator"
                  xmlns:tns="http://example.org/calculatorService"
                  targetNamespace="http://example.org/calculatorService">

    <!--
      Abstract type definitions
    -->

    <wsdl:types>
        <!--
        <xs:schema>
            <xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
        </xs:schema>
        -->
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:tns="http://example.org/calculator"
                   targetNamespace="http://example.org/calculator"
                   elementFormDefault="qualified"
                   attributeFormDefault="qualified">

            <xs:element name="AddValuesRequest" type="tns:AddValuesType" />
            <xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />

            <xs:complexType name="AddValuesType">
                <xs:sequence>
                    <xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                    <xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                </xs:sequence>
            </xs:complexType>

            <xs:complexType name="AddValuesResponseType">
                <xs:sequence minOccurs="1" maxOccurs="1">
                    <xs:element name="Result" type="xs:int" />
                </xs:sequence>
            </xs:complexType>

            <xs:attribute name="Timestamp" type="xs:dateTime" />
            <xs:element name="CalculationFailure">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="ErrorCode" type="xs:int" />
                        <xs:element name="Reason" type="xs:string" />
                    </xs:sequence>
                    <xs:attribute ref="tns:Timestamp" use="required" />
                </xs:complexType>
            </xs:element>

        </xs:schema>
    </wsdl:types>

    <!--
        Abstract message definitions
    -->

    <wsdl:message name="AddValuesRequest">
        <wsdl:part name="in" element="calc:AddValuesRequest" />
    </wsdl:message>
    <wsdl:message name="AddValuesResponse">
        <wsdl:part name="out" element="calc:AddValuesResponse" />
    </wsdl:message>
    <wsdl:message name="CalculationFault">
        <wsdl:part name="fault" element="calc:CalculationFailure" />
    </wsdl:message>

    <!--
        Abstract portType / interface definition
    -->

    <wsdl:portType name="CalculatorEndpoint">
        <wsdl:operation name="AddValues">
            <wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
            <wsdl:input message="tns:AddValuesRequest" />
            <wsdl:output message="tns:AddValuesResponse" />
            <wsdl:fault name="CalculationFault" message="tns:CalculationFault" />
        </wsdl:operation>
    </wsdl:portType>

    <!--
      Concrete binding definition
    -->

    <wsdl:binding name="CalculatorBinding" type="tns:CalculatorEndpoint">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="AddValues">
            <soap:operation soapAction="http://example.org/calculator/AddValuesMessage" />
            <wsdl:input>
                <soap:body parts="in" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body parts="out" use="literal" />
            </wsdl:output>
            <wsdl:fault name="CalculationFault">
                <soap:fault name="CalculationFault" use="literal" />
            </wsdl:fault>
        </wsdl:operation>
    </wsdl:binding>

    <!--
        Concrete service definition
    -->

    <wsdl:service name="CalculatorService">
        <wsdl:port name="CalculatorServicePort" binding="tns:CalculatorBinding">
            <soap:address location="http://localhost:8080/services/calculator" />
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>
 

service 部分定义服务将侦听传入请求的具体端点。 binding 部分将操作绑定到具体样式,并定义服务器期望或客户端可以期望的消息格式。

抽象部分由portType 块组成,该块定义服务提供的操作以及交换的消息。消息在其on块中指定,并链接到参数和返回值为实例的模式类型。消息可以声明参数或返回值为inoutinout 。虽然前两个很容易掌握,后者模仿参考传递的参数的行为。由于某些语言不支持pass-by-ref,因此通常会通过某些处理程序模拟此效果。

WSDL 2.0

可以在WSDL 2.0中描述相同的计算器,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<wsdl:description xmlns:xs="http://www.w3.org/2001/XMLSchema"
                  xmlns:wsdl="http://www.w3.org/ns/wsdl"
                  xmlns:soap="http://www.w3.org/ns/wsdl/soap"
                  xmlns:calc="http://example.org/calculator"
                  xmlns:tns="http://example.org/calculatorService"
                  targetNamespace="http://example.org/calculatorService">

    <!--
      Abstract type definitions
    -->

    <wsdl:types>
        <!--
        <xs:schema>
            <xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
        </xs:schema>
        -->
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:tns="http://example.org/calculator"
                   targetNamespace="http://example.org/calculator"
                   elementFormDefault="qualified"
                   attributeFormDefault="qualified">

            <xs:element name="AddValuesRequest" type="tns:AddValuesType" />
            <xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />

            <xs:complexType name="AddValuesType">
                <xs:sequence>
                    <xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                    <xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                </xs:sequence>
            </xs:complexType>

            <xs:complexType name="AddValuesResponseType">
                <xs:sequence minOccurs="1" maxOccurs="1">
                    <xs:element name="Result" type="xs:int" />
                </xs:sequence>
            </xs:complexType>

            <xs:attribute name="Timestamp" type="xs:dateTime" />
            <xs:element name="CalculationFault">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="ErrorCode" type="xs:int" />
                        <xs:element name="Reason" type="xs:string" />
                    </xs:sequence>
                    <xs:attribute ref="tns:Timestamp" use="required" />
                </xs:complexType>
            </xs:element>

        </xs:schema>
    </wsdl:types>

    <!--
        Abstract interface
    -->

    <wsdl:interface name="CalculatorInterface">
        <wsdl:fault name="fault" element="calc:CalculationFault" />
        <wsdl:operation name="AddValues" pattern="http://www.w3.org/ns/wsdl/in-out" style="http://www.w3.org/ns/wsdl/style/iri" wsdl:safe="true">
            <wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
            <wsdl:input messageLabel="in" element="calc:AddValuesRequest" />
            <wsdl:output messageLabel="out" element="calc:AddValuesResponse" />
            <wsdl:outfault messageLabel="fault" ref="tns:fault" />
        </wsdl:operation>
    </wsdl:interface>

    <!--
        Concrete binding definition
    -->

    <wsdl:binding name="CalculatorBinding" interface="tns:CalculatorInterface" type="http://www.w3.org/ns/wsdl/soap" soap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/">
        <wsdl:operation ref="tns:AddValues" soap:mep="http://www.w3.org/2003/05/soap/mep/soap-response" />
        <wsdl:fault ref="tns:fault" soap:code="soap:Sender" />
    </wsdl:binding>

    <!--
        Concrete service definition
    -->

    <wsdl:service name="CalculatorService" interface="tns:CalculatorInterface">
        <wsdl:endpoint name="CalculatorEndpoint" binding="tns:CalculatorBinding" address="http://localhost:8080/services/calculator" />
    </wsdl:service>

</wsdl:description>
 

WSDL 1.1和2.0之间的差异

有关两个版本之间差异的图形概述,请参见下图。

在此处输入图像描述来源

从图像中可以看出message 部分已被删除,现在包含在interface 部分中。此外,一些元素已重命名,其他元素具有不同的语法,但通常两个WSDL版本与版本2.0基本相同,与1.1相比需要更少的写入开销。

除了通过WSDL 2.0定义基于SOAP的服务的占地面积较小之外,较新的版本还提供了定义REST服务的功能,尽管WSDL 2.0甚至WADL不建议用于RESTful服务,因为它们与其背后的实际想法相矛盾。

喜欢哪种风格

WSDL绑定部分描述了服务如何绑定到SOAP消息传递协议。上面的示例使用document 作为绑定样式,只要结果输出是有效的XML实例,就可以按照我们想要的方式构造SOAP主体。这是默认的绑定样式,通常称为Message-Oriented style

document 样式相比, RPC 样式请求主体必须包含操作名称和方法参数集。因此,XML实例的结构是预定义的,无法更改。

除了绑定样式之外,绑定部分还定义了一个转换模型,用于以literalencoded 的名义绑定到SOAP消息。两者之间的区别在于, literal 模型必须符合用户定义的XSD结构,可用于验证请求和响应,而encoded 模型必须使用XSD数据类型,如xs:integerxs:string 但因此,交换不符合任何用户定义的模式。但是,这使得更难以验证消息体或通过XSLT将消息转换为其他格式。

绑定样式与使用模型的组合实际上允许4种不同的消息结果。第5个条目被添加到常用的列表中(虽然不是标准的一部分)。

  • RPC /编码
  • RPC / literal
  • 文件/编码
  • 文件/文字
  • 文件/文字(包裹)

在文档/文字样式的消息传递中,存在一种称为wrapped-document / literal的模式。这只是一种模式,并不是WSDL规范的一部分。在JSR 224(JAX-WS:基于XML的Web服务的Java API)中提到了这种模式。 ( 来源

以下部分概述了有关WSDL或模式声明的差异及其在更改绑定样式或使用模型定义时对生成的SOAP消息格式的影响。

RPC /编码

WSDL:

...
<wsdl:message name="AddValues">
  <wsdl:part name="FirstValue" type="xsd:int" />
  <wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="Result" type="xsd:int" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'RPC' and use to 'encoded' -->
...
 

SOAP请求

<soap:envelope>
  <soap:body>
    <AddValues>
      <FirstValue xsi:type="xsd:int">1</FirstValue>
      <SecondValue xsi:type="xsd:int">2</SecondValue>
    </AddValues>
  </soap:body>
</soap:envelope>
 

SOAP响应

<soap:envelope>
  <soap:body>
    <AddValuesResponse>
      <Result xsi:type="xsd:int">3</Result>
    </AddValuesResponse>
  </soap:body>
</soap:envelope>
 

优点

  • 直截了当的WSDL
  • 请求和响应中可用的操作名称和元素

缺点

  • XSI类型的明确声明
  • 很难验证
  • 不符合WS-I标准

RPC / literal

WSDL:

...
<wsdl:message name="AddValues">
  <wsdl:part name="FirstValue" type="xsd:int" />
  <wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="Result" type="xsd:int" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'RPC' and use to 'literal' -->
...
 

SOAP请求

<soap:envelope>
  <soap:body>
    <AddValues>
      <FirstValue>1</FirstValue>
      <SecondValue>2</SecondValue>
    </AddValues>
  </soap:body>
</soap:envelope>
 

SOAP响应

<soap:envelope>
  <soap:body>
    <AddValuesResult>
      <Result>3</Result>
    </AddValuesResult>
  </soap:body>
</soap:envelope>
 

优点

  • 直截了当的WSDL
  • 请求和响应中可用的操作名称和元素
  • 不需要XSI类型规范
  • 符合WS-I标准

缺点

  • 很难验证

文件/编码

因此省略没有任何意义。

文件/文字

WSDL:

...
<types>
  <schema>
    <element name="FirstValueElement" type="xsd:int" />
    <element name="SecondValueElement" type="xsd:int" />
    <element name="ResultValueElement" type="xsd:int" />
  </schema>
</types>

<wsdl:message name="AddValues">
  <wsdl:part name="FirstValue" element="FirstValueElement" />
  <wsdl:part name="SecondValue" element="SecondValueElement" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="Result" element="ResultValueElement" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'Document' and use to 'literal' -->
...
 

SOAP请求

<soap:envelope>
  <soap:body>
    <FirstValueElement>1</FirstValueElement>
    <SecondValueElement>2</SecondValueElement>
  </soap:body>
</soap:envelope>
 

SOAP响应

<soap:envelope>
  <soap:body>
    <ResultElement>3</ResultElement>
  </soap:body>
</soap:envelope>
 

优点

  • 没有XSI类型编码
  • 能够验证身体
  • WS-I符合限制

缺点

  • 由于额外的XSD定义,WSDL更复杂
  • 操作名称丢失
  • WS-I只允许SOAP体中的一个子节点

文件/文字(包裹)

WSDL:

...
<types>
  <schema>
    <element name="AddValues">
      <complexType>
        <sequence>
          <element name="FirstValue" type="xsd:int" />
          <element name="SecondValue" type="xsd:int" />
        </sequence>
      </complexType>
    </element>
    <element name="AddValuesResponse">
      <complexType>
        <sequence>
          <element name="ResultValue" type="xsd:int" />
        </sequence>
      </complexType>
    </element>
  </schema>
</types>

<wsdl:message name="AddValues">
  <wsdl:part name="in" element="AddValues" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="out" element="AddValuesResponse" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'Document' and use to 'literal' -->
...
 

SOAP请求

<soap:envelope>
  <soap:body>
    <AddValues>
      <FirstValue>1</FirstValue>
      <SecondValue>2</SecondValue>
    </AddValues>
  </soap:body>
</soap:envelope>
 

SOAP响应

<soap:envelope>
  <soap:body>
    <AddValuesResponse>
      <Result>3</Result>
    </AddValuesResponse>
  </soap:body>
</soap:envelope>
 

优点

  • 没有XSI类型编码
  • 能够验证身体
  • 请求和响应中可用的操作名称和元素
  • 符合WS-I标准

缺点

  • 由于额外的XSD定义,WSDL更复杂

UDDI

Universal Description, Discovery and Integration (UDDI) 是一个在2000年创建的开放式行业计划,它充当基于XML的黄页网页服务注册表,有助于查找解决特定任务的服务。为了找到适当的服务,需要首先使用Web服务注册表(如UDDI)注册服务。

UDDI处理SOAP消息交换,并提供对WSDL文档的访问,这些文档可用于调用实际的Web服务。

UDDI提供了诸如的查找标准

  • 业务标识符
  • 公司名称
  • 营业地点
  • 业务类别
  • 服务类型名称
  • 发现网址

但是,当前UDDI的一大缺点是它只允许在搜索语句中使用一个单一条件。因此,某些实现者将其UDDI实现模块化,以允许同时生成多个UDDI的查询,然后聚合返回的结果。

然而,在实践中,经常不使用UDDI。有些人甚至说UDDI已经死了,因为IBM,微软和SAP 在2005年关闭了他们的UDDI服务

附加说明:

SOAP / WSDL提供了广泛的工具支持,并且还允许为客户端和服务器动态生成存根类,因为通过嵌入或链接的XSD模式很好地定义了消息和数据交换的类型。

虽然WSDL 2.0定义Web服务的开销较小,但某些语言尚未采用新标准。即Java中流行的工具,如wsimport (来自Oracle / Sun)或wsdl2java (来自Apache CXF),无法正确处理WSDL 2.0描述。因此,出于兼容性原因,仍建议使用WSDL 1.1。如果需要在Java中开发基于WSDL 2.0的SOAP服务,请查看Apache Axis2项目中的wsdl2java

然而,现在比较流行的是基于HTTP的API服务,它将HTTP操作调用与干净的人类可理解的URI混合,并对协议进行某些自定义以完成其工作,基于REST的服务完全符合实际建议,或者自己的字节级协议,例如OFTP2

如果您无法将任务直接映射到资源(如HTTP / REST基本服务),SOAP现在仍然很有用,因为要实现的任务自然代表一个操作或必须定义某些事务语义。此外,如果您没有资源来定义或实现自己的协议,那么您最好使用SOAP。如果您必须处理业务流程,SOAP特别有用,因为WSDL描述与UDDI结合允许动态组合服务。

Java Client for Weather服务开源web服务可在http://www.webserviceX.NET上获得

  package com.test.ws.example;

 import javax.xml.soap.MessageFactory;
 import javax.xml.soap.MimeHeaders;
 import javax.xml.soap.SOAPBody;
 import javax.xml.soap.SOAPConnection;
 import javax.xml.soap.SOAPConnectionFactory;
 import javax.xml.soap.SOAPElement;
 import javax.xml.soap.SOAPEnvelope;
 import javax.xml.soap.SOAPMessage;
 import javax.xml.soap.SOAPPart;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.stream.StreamResult;

 /*
  * WSDL url :  http://www.webservicex.com/globalweather.asmx?WSDL
  * Endpoint URL: http://www.webservicex.com/globalweather.asmx   */

    public class WSClient {

   public static void main(String args[]) {

    try {
        SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
        SOAPConnection soapConnection = soapConnectionFactory.createConnection();

        // Generate SOAP request XML

        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        MimeHeaders header = soapMessage.getMimeHeaders();
        header.setHeader("SOAPAction", "http://www.webserviceX.NET/GetCitiesByCountry");
        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.addNamespaceDeclaration("web", "http://www.webserviceX.NET");
        SOAPBody soapBody = envelope.getBody();
        SOAPElement soapBodyElem = soapBody.addChildElement("GetCitiesByCountry", "web");
        SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("CountryName", "web");
        soapBodyElem1.addTextNode("INDIA");
        soapMessage.saveChanges();
        soapMessage.writeTo(System.out);
        
                    
        // Call webservice endpint
        String url = "http://www.webservicex.com/globalweather.asmx";
        SOAPMessage soapResponse = soapConnection.call(soapMessage, url);
        Source sourceContent = soapResponse.getSOAPPart().getContent();

        // Print SOAP response
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        System.out.println("Response SOAP Message \n");
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
        soapConnection.close();

    } catch (Exception e) {

        e.printStackTrace();
    }
}
 

}