WebService and SOAP

第一部分

什么是 Web 服务?

首先,让我们从总体上了解一下什么是 Web 服务,以及它们为何对软件开发重要。

究竟为什么重要呢?

如果您没有听说过有关面向服务的体系结构 (SOA) Web 服务的大量信息,您就不会阅读本文,那么问题就应该是,为什么此内容这样重要?答案是,此内容之所以重要,是因为这是应用程序彼此进行通信的方式的典型变化。SOAs 已经存在很长很长时间了。SOA 最初主要由中间件应用程序组成,至少进行连接的两端都属于同一种类型的中间件。另一方面,Web 服务由一组标准组成,用于在不需要特定类型的中间件、编程语言甚至操作系统的前提下让各种不同的系统进行通信。接下来,让我们了解一下其发展的历程。

传统应用程序

首先从计算机发明开始,当时给人感觉非常不错。计算机能执行奇迹般的任务,可实现很多手动工作的自动化,包括复杂的计算、财务工作等等很多其他任务。

但传统应用程序是竖井”(Silo) 型的。人力资源应用程序无法与财务应用程序真正通信,而后者又无法和分布应用程序进行真正的通信。所有这些应用程序都有独立的领域,在独立的计算机上运行,尽管很有用,但并不能很好地在彼此间共享数据。当时可以选择对批处理流程进行连接,以将数据从一个系统移动到另一个系统,但这并不适合进行实时集成。

分布式计算

在我们的进化链中的第二步是分布式计算。分布式计算允许不同的应用程序彼此进行通信(即使位于不同的计算机上也是如此)。CORBAMTS Enterprise Java Bean (EJB) 等技术提供了包含各种类别的注册中心的系统,因此应用程序可以找到其希望与之进行交互的组件,然后像调用本地的组件一样调用这些组件。

这些系统由可同时满足这两个要求的中间件(或更具体一些,面向消息的中间件)提供支持。现在能以特定的方式构建应用程序,即使位于不同的地理位置,也能访问其他系统上的资源。

但仍然有一个问题。虽然系统可以自由地与系统内的任何对象进行通信,但仍然是一个封闭的系统。至少,客户机应用程序必须与服务器应用程序使用相同的技术。另外,通常并不会将系统设计为从创建其的个体组织外进行访问。

Web 服务

此进化链中下一个几乎不可避免的链接点就是 Web 服务。“Web 服务基于 XML HTTP(大多数情况下),对很多人具有不同的含义,但在此处,我们要将 Web 服务作为系统间基于 SOAP 的消息交换进行讨论。

这些消息由 XML 组成(XML 是一个基于文本的开放标准),可由来自任何应用程序(任何设计为接收此类消息的应用程序)的任何人进行访问。这就扩展了应用程序的范围,从而包含任何可通过网络对其进行访问的任何人。(如果这让您开始考虑安全问题,不要紧,您将在本系列的第 4 部分了解如何处理这方面的问题。)

基于 SOAP Web 服务将要发送与清单 1 中所示类似的 XML 消息。


清单 1. 基于 SOAP Web 服务

                   

<SOAPenv:Envelope

       xmlns:SOAPenv="http://schemas.xmlSOAP.org/SOAP/envelope/"

       xmlns:xsd="http://www.w3.org/2001/XMLSchema"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <SOAPenv:Body>

 <req:getNumberOfArticles xmlns:req="http://daily-moon.com/CMS/">

     <req:category>classifieds</req:category>

 </req:getNumberOfArticles>

 </SOAPenv:Body>

</SOAPenv:Envelope>

这些消息将从一个系统进入另一个系统(通常通过 HTTP)。接收系统对消息进行解释,进行应该进行从处理,然后发送另一个 SOAP 消息作为响应。

这个系统很简单,正因为如此,有很多企业级计算方面的内容都尚未涉及。幸运的是,其中的很多方面已被纳入考虑范畴,且具有自己的相关规范来确定此事务应如何进行,以包含传统的面向消息的中间件的很多安全和其他方面的内容。

其他类型的 Web 服务

如果我没有说明 SOAP 并不是唯一的处理 Web 服务的方法,那就有些失职了。有很多其他基于 XML 的方法用于在系统间发送信息,其中一些适用于企业环境,而另一些则不适合此用途。例如,Amazon 是为公众提供对其系统的 Web 服务访问的第一批基于 Web 服务的公司之一。Amazon 包含了一个基于 SOAP 的服务,但也提供了一个基于 Representational State Transfer (REST) 的服务。

REST 是一种 Web 服务类型,其中,用户直接访问 URL,相应的响应是与清单 2 中所示类似的简单 XML 文档。


清单 2. REST 响应

                   

<currentArticles>

   <category>classifieds</category>

   <subcategory>forsale</subcategory>

   <article id="888204">

       <articleHeadline></articleHeadline>

       <articleText>30 ft ladder, only used once. Willing to let

go for half it's worth. Has slight dent near the middle. 

Harder than a human head. $150 OBO.</articleText>

    </article>

   <article id="888242">

       <articleHeadline></articleHeadline>

       <articleText>Vintage 1963 T-Bird. Less than 300 miles. 

Driven by my daughter until I took it away. Serious inquires only.

555-3264 after 7 PM.</articleText>

    </article>

</currentArticles>

这些消息并没有特定的格式。可以为任何数据。

另一种 Web 服务类型要使用 XML-RPC 之类的标准。在这种情况下,命令将通过与清单 3 中所示类似的 XML 发送到系统。


清单 3. XML-RPC

                   

<?xml version="1.0"?>

<methodCall>

   <methodName>CMS.getNumberOfArticles</methodName>

   <params>

      <param>

         <value><string>classifieds</string></value>

      </param>

      <param>

         <value><string>forsale</string></value>

      </param>

   </params>

</methodCall>

其响应将采用类似的格式。

在学习使用 SOAP 的过程中,您可以会打心底里认为 REST XML-RPC 比基于 SOAP 的系统要简单得多。的确如此。在某些情况下 REST XML-RPC SOAP 系统简单。不过,我们讨论的不是在网站上显示天气的简单应用程序。我们此处讨论的是企业级应用程序,而企业级的应用程序需要企业级的属性,如安全、互操作性等等。这些功能在有关基于 SOAP Web 服务的其他规范中进行了定义,因而,从长期来看,SOAP 更适合用于企业级应用程序。

让我们了解一下这些规范。

基本 Web 服务规范

Web 服务规范通常归为两类:基本 Web 服务规范和扩展 Web 服务规范。基本规范有:

  • SOAPSOAP 规范是所有基于 SOAP Web 服务的基础,详细说明了实际消息的格式。其中还详细说明了应用程序应如何对待消息的特定方面(如“Header”中的元素),从而可以创建特定类型的应用程序,使其中的消息在达到最终的目的地前在多个中间层之间进行传递。本教程将涵盖 SOAP 规范的内容。
  • WDSLWeb 服务描述语言是详细说明描述基于 SOAP Web 服务的标准方式的规范,包括消息应采用的形式以及应将其发送到何处。其中还详细说明了此类消息的响应。当与相应的工具结合使用时,WSDL 允许以编程方式创建对 Web 服务的调用,甚至不用知道所查找的 Web 服务是什么;应用程序可以从 WSDL 文件中提取这些详细信息,并提供要使用的编程接口。我们将在本系列的第 2 部分讨论 WSDL
  • UDDI:统一描述、发现和集成 (Universal Description, Discovery and Integration) 是一项从最初提出后发生了一系列变化的标准。其最初的目的是为了给各个公司提供在全球注册中心中注册服务并在此注册中心中搜索可能想使用的服务的机制。不过,由于很多公司对于将其系统对外开放的问题上都相当保守,这个目标并没有完全实现。但是,很多公司已将 UDDI 作为内部的服务及服务信息注册中心使用,本系列第 3 部分将对其使用进行详细论述。

以上是一些基础知识。另外差不多还有数十种扩展标准,可进一步扩展基于 SOAP 的服务的用途。

扩展 Web 服务规范

总共有数十种 WS-* 规范,其中几种对企业尤为有用。即:

  • WS-Security:此规范处理加密和数字签名,允许创建特定类型的应用程序,以防止窃听消息,且能实现不可否认功能。本系列的第 4 部分将讨论 WS-Security
  • WS-Policy:此规范对 WS-Security 进行了扩展,允许更具体地说明谁可以采用何种方式使用服务。本系列的第 5 部分将讨论 WS-Policy
  • WS-I:尽管 Web 服务应设计成具有互操作性,但在实际中,各个规范对不同实现的解释的灵活性常常足以导致出现问题。WS-I 提供了一组可用于防止出现各种问题的标准和实践,并提供了标准化测试来检查问题。WS-I 是本系列的第 6 部分将要讨论的主题。
  • WS-BPEL:单个服务很好处理,但应用程序在大多数情况下则较难处理。企业级计算要求至少将多个服务组合为一个完整的系统,而 WS-BPEL 提供了用于指定创建此类系统所必需的交互(如分支和并发处理)。本系列的第 7 部分将讨论 WS-BPEL

Web 服务中扮演重要角色的其他规范将不在本系列中讨论,其中包括WS-ReliableMessaging(允许确定检索一个且仅一个消息副本)、Web 服务资源框架 (WSRF)(允许使用在无状态环境中非常重要的状态)和 Web 服务分布式管理 (WSDM)(讨论 Web 服务的管理和使用问题)。

第二部分

理解 SOAP

现在已经安装了软件,接下来可以开始着手处理实际的 Web 服务了。正如我在其他类型的 Web 服务中提到的,您可以选择多种格式。在本系列中,将使用 SOAP

XML 简介

进行传递的所有这些消息都基于可扩展标记语言(Extensible Markup LanguageXML)。如果完全不熟悉 XML,在深入了解各个 Web 服务主题前,真的应该进行一些相关研究。不过,以下提供了继续学习本教程所需的基本知识。

XML 是一种标记语言,即给出了一种提供实际内容的附加信息的方式。此信息以标记的形式提供,这些标记用于指示元素。例如,考虑一下清单 5 中所示的简单 XML 文档。


清单 5. 包含基本内容的 XML 文件

                   

<article articleId="88271" categoryId="classifieds" subcategoryId="forsale">

 <articleHeadline>Fun, fun, fun</articleHeadline>

 <articleText>Vintage 1963 T-Bird. Less than 300 miles.

Driven by my daughter until I took it away. Serious

inquires only. 555-3264 after 7 PM.</articleText>

</article>

请留意此文本中的几个值得注意的地方。首先,这是文本。这就使其可以供任何人阅读,或在其中包含关于任何事物的内容。其次,标记使用 > < 指示,开始标记具有一个名称,并可能带有各种属性(如文章 ID),而结束标记以反斜杠 (/) 表示。元素必须为自包含的,并进行了恰当嵌套。也就是说,不能使用与清单 6 所示类似的 XML 文档。


清单 6. 无效 XML 文档示例

                   

<article articleId="88271" categoryId="classifieds" subcategoryId="forsale">

 <articleHeadline>Fun, fun, fun

 <articleText></articleHeadline>Vintage 1963 T-Bird. 

Less than 300 miles. Driven by my daughter until I

took it away.  Serious inquires only. 555-3264 after

7 PM.</articleText>

</article>

XML 还提供了将内容划分为不同命名空间的方法,以便由应用程序对其进行不同的处理。例如,SOAP 消息可能与以下的清单 7 类似。


清单 7. 示例 SOAP 消息

                   

<?xml version='1.0' ?>

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

 </env:Header>

 <env:Body>

 <cms:getNumberOfArticles xmlns:cms="http://www.daily-moon.com/cms">

    <cms:category>classifieds</cms:category>

    <cms:subcategory>forsale</cms:subcategory>

 </cms:getNumberOfArticles>

 </env:Body>

</env:Envelope>

不要担心消息的实际结构,但要注意存在两种不同的前缀,每个前缀与特定的命名空间对应。在这种情况下,我们是为了将 SOAP“信封与实际的有效负载进行区分。

再次说明,关于 XML 有很多需要学习,但这些只是本教程需要了解的基础知识。

SOAP 信封

Web 服务消息的基本单元是实际的 SOAP 信封。这是包含处理消息所必需的所有信息的 XML 文档(请参见清单 8)。


清单 8. 示例 SOAP 信封

                   

<?xml version='1.0' ?>

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

</env:Header>

<env:Body>

</env:Body>

</env:Envelope>

在本例中,获得了一个简单的Envelope,其命名空间指定为 SOAP 1.2 版本。其中包含两个子元素HeaderBody。让我们了解一下这两个子元素所起的作用。

SOAP Header

SOAP 消息中的Header用于提供有关消息本身的信息,与用于应用程序的信息相对。例如,Header可以包括路由信息,像清单 9 中的示例类似。


清单 9. Header 中的路由信息

                   

<?xml version='1.0' ?>

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

 <wsa:ReplyTo xmlns:wsa=

        "http://schemas.xmlSOAP.org/ws/2004/08/addressing">

   <wsa:Address>

http://schemas.xmlSOAP.org/ws/2004/08/addressing/role/anonymous

   </wsa:Address>

 </wsa:ReplyTo>

 <wsa:From>

   <wsa:Address>

http://localhost:8080/axis2/services/MyService</wsa:Address>

 </wsa:From>

 <wsa:MessageID>ECE5B3F187F29D28BC11433905662036</wsa:MessageID>

 </env:Header>

<env:Body>

</env:Body>

</env:Envelope>

本例中有一个 WS-Addressing 元素,其中包含有关消息将送达何处以及应将应答送达何处的信息。Header可包含关于消息本身的所有类型的消息。事实上,SOAP 规范中使用了大量篇幅说明哪些元素可以放入Header以及应由“SOAP 中间层如何对其进行处理。也就是说,SOAP 规范并不假定消息将直接从一个点传递到另一个点(从客户机到服务器)。规范考虑了 SOAP 消息在送达最终目的地的过程中可能实际由多个中间层处理的情况,很清楚地说明了中间层应如何对待在Header中找到的信息。不过,对此的讨论不在本教程的范围之内。因此,目前只要知道Header可以提供许许多多的功能(如果您需要)即可。

接下来让我们看看实际的有效负载。

SOAP

发送 SOAP 消息时,都是有目的性的。您在尝试告诉接收者执行某种操作,或尝试向服务器传递相关信息。此信息称为有效负载。有效负载位于EnvelopeBody中。它还具有自己的命名空间,在本例中其命名空间与内容管理系统对应。在此情况下,可以完全随意地选择命名空间。只需要与 SOAP 命名空间相异即可(请参见清单 10)。


清单 10. 有效负载示例

                   

<?xml version='1.0' ?>

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

...

</env:Header>

 <env:Body>

 <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">

    <cms:category>classifieds</category>

    <cms:subcategory>forsale</cms:subcategory>

    <cms:articleHeadline></cms:articleHeadline>

    <cms:articleText>Vintage 1963 T-Bird. Less than 300 miles. 

Driven by my daughter until I took it away. Serious inquires only. 

555-3264 after 7 PM.</cms:articleText>

 </cms:addArticle>

 </env:Body>

</env:Envelope>

在此例中,有效负载很简单,其中包含将文章添加到 Daily Moon的内容管理系统的指令。

如何设计有效负载的选择过程将涉及到样式和编码的内容。

样式和编码

本系列教程的第 2 部分将更深入地了解此主题的内容(该部分讨论 Web 服务描述语言——WSDL),但在创建应用程序时,您将需要确定要发送和接收的实际有效负载的结构。为此,让我们花点时间讨论一下编程样式和编码。

简单来说,有两种不同的主流 SOA 消息编程样式。第一种是 RPC 样式,基于使用 SOAP 消息创建远程过程调用(Remote Procedure Call)的概念。在此样式中,基本思路是在向服务器发送命令(如添加文章),并将该命令的参数(如要添加的文章和应该添加到的类别)作为整个方法的子元素包含在其中,如清单 11 中所示。


清单 11. RPC 样式

                   

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

RPC 样式的替代方法将数据直接作为 SOAP 体的内容处理,并在应用服务器对消息进行路由的信息中包含有关其所属的过程或函数的信息。(请参见清单 12)。


清单 12. 将数据作为 SOAP 体中的内容

                    

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

 </env:Header>

 <env:Body>

 <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">

    <cms:category>classifieds</category>

    <cms:subcategory>forsale</cms:subcategory>

    <cms:articleHeadline></cms:articleHeadline>

    <cms:articleText>Vintage 1963 T-Bird. Less than 300

miles. Driven by my daughter until I took it away. 

Serious inquires only. 555-3264 after 7 PM.</cms:articleText>

 </cms:addArticle>

 </env:Body>

</env:Envelope>

RPC 样式的一个变体就是与上面看到的 RPC/literal 相对的 RPC/encoded。在这种情况下,消息中包含类型信息,如清单 13 中所示。


清单 13. RPC/encoded 示例

                   

<?xml version='1.0' ?>

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

 </env:Header>

 <env:Body>

 <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">

    <cms:category xsi:type="xsd:string">classifieds</category>

    <cms:subcategory xsi:type="xsd:string">forsale

</cms:subcategory>

    <cms:articleHeadline xsi:type="xsd:string" />

    <cms:articleText xsi:type="xsd:string">Vintage 1963

T-Bird. Less than 300 miles. Driven by my daughter until

I took it away. Serious inquires only. 555-3264 after 7

PM.</cms:articleText>

 </cms:addArticle>

 </env:Body>

</env:Envelope>

第二个样式称为 document/literal 样式,即将相应的数据直接添加到消息中,如清单 14 中所示。


清单 14. Document/literal 样式示例

                   

<?xml version='1.0' ?>

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

 <env:Header>

 </env:Header>

 <env:Body>

   <category>classifieds</category>

    <subcategory>forsale</subcategory>

    <articleHeadline></articleHeadline>

    <articleText>Vintage 1963 T-Bird. Less than 300 miles.

 Driven by my daughter until I took it away. Serious

inquires only. 555-3264 after 7 PM.</articleText>

</env:Body>

</env:Envelope>

在这种情况下,消息本身并不包含有关数据所提交到的进程的信息,此工作由路由软件进行。例如,所有对特定 URL 或端点的调用都可能指向特定的操作。另外,从技术上讲,可以使用 document/encoded 样式,但目前还没有人这样做,因此可以将其忽略。

在每个样式中都涉及到不同的折衷,本系列的第 2 部分将进一步对此进行详细讨论。不过,务必知道还有第三种样式“document wrapped”,并未正式地确定此样式,但由于各种互操作性原因而大受欢迎。在此情况下,有效负载的内容包装为单个元素,但元素并不据数据所属的过程或函数进行命名。从肉眼来看,这些消息几乎与 RPC/literal 消息完全相同。

消息交换模式

谈到发送消息,您有很多选择,可以发送请求并等待响应,发送请求但不等待响应,发送请求并在到达最终的目的地前通过多个中间层。但就实质而言,只有两个选择:

  • 请求/响应:在请求/响应模式种,以 SOAP 消息的形式发送请求,然后直接等待发送回响应。请求可以为同步的,也可以是异步的。
  • 单向消息传递:这种情况也称为“Fire and Forget”方法,发送请求但并不等待响应。可以在仅传递信息时或并不关心接收者对此如何响应时使用此方法。

现在,请注意并没有使用术语客户机服务器。之所以这样,是因为这些消息交换模式几乎可以用于创建与上面提到的方法类似的任意数量的不同备选方法。例如,可以发送一条请求,然后依靠接收者对其进行处理,并在将来完成应完成的工作时发送一条消息。为此,将使用多个单向消息的组合,因此谈客户机服务器并不合理,因为每个消息都有其接收方和发送方,所谓的客户机和服务器的位置会发生对换。

原文地址:https://www.cnblogs.com/engine1984/p/1103845.html