了解 Web 服务规范: 第 3 部分:统一描述、发现和集成 (UDDI) (2)

了解 Web 服务规范: 第 3 部分:统一描述、发现和集成 (UDDI) (2)

UDDI 数据结构

为了开始将公司添加到 UDDI 注册中心,Francis 定义了要输入注册中心的信息。

businessEntity

第一步是将报社本身的信息输入注册中心。为此,Francis 创建了一个 businessEntity 对象。此对象包含有关企业的信息,既用于对企业进行标识,也用于提供与其有关的信息。例如,businessEntity 对象可以包含多个名称(从而能够为公司所使用的每种语言创建一个 name 元素),联系信息(Francis 被告知将 Pat Mooney 添加为主要联系人)、与实体相关的服务(Gene 将稍后添加)和用于对公司进行标识与分类的信息。

尽管大部分人都不会采用这种方式与 UDDI 注册中心交互,但要注意的一个事实是,UDDI 实际上就是 SOAP 应用程序;执行的所有操作都作为往返传递 SOAP 消息的结果发生。这意味着,Francis 所创建的 businessEntity 最终将表示为 XML 元素。请参见清单 2。


清单 2. businessEntity 元素
												
														<businessEntity businessKey="{uuid}"
												 operator="(optional)" 
authorizedName="(optional)">
<discoveryURLs>
<discoveryURL></discoveryURL>
<discoveryURL></discoveryURL>
</discoveryURLs>
<name>The Daily Moon</name>
<name lang="fr-ca">La Lune Quotidienne</name>
<description></description>
<contacts>
<contact>
<description></description>
<personName>Pat Mooney</personName>
<phone></phone>
<email>[email protected]</email>
<address useType="optional, billing, etc." 
sortCode="optional" 
tModelKey="optional">
<addressLine></addressLine>
<addressLine></addressLine>
<addressLine></addressLine>
</address>
</contact>
<contact>
         ...
</contact>
</contacts>
<businessServices>
<businessService serviceKey="required" 
businessKey="optional">
         ...
</businessService>
</businessServices>
<identifierBag>
      ...
</identifierBag>
<categoryBag>
      ...
</categoryBag>
</businessEntity>

businessEntity 记录并不一定要很复杂。事实上,按照 businessKey 的要求,单个名称和一个唯一标识符就足够了。不过,出于完整性考虑,我包含了完整的结构,但去掉了一些稍后将另行讨论的部分。在生产环境中,应将空白元素删除。

让我们看一看此处的一些信息。

从代码的起始处开始,businessKey 当然是唯一标识符。operator 和 authorizedName 属性由注册中心内部进行处理;您不必考虑这部分内容,它们仅仅分别表示运行注册中心的实体和添加此记录的人员或帐户。

discoveryURLs 会在每次将 businessEntity 保存到注册中心时添加到注册中心。这些 URL 旨在用作供用户访问有关 businessEntity 的更多信息的地址。

请注意,Francis 添加了一个额外的名称,用于以法语表示其名称(报社打算在法国宣传其业务)。这些实体中的每一个都具有 lang 属性,用于指定相关语言的代码。您可以提供常见缩写的可替换名称,如 IBM 对应于 International Business Machines。

接下来的可选描述是一个简单的文本字符串。事实上,UDDI 中的大部分元素都具有一个可选描述。

接下来,Francis 添加了其他一些联系人。对于每个联系人,他可以根据需要指定任意多的信息。通常会提供 personName,但电话号码、电子邮件等其他信息是由个人自行提供的,因为 UDDI 注册中心的所有信息对所有用户均可用。联系人还可能具有地址信息,使用 useType 来指定地址类型。例如,对于联系人,它可以为家庭地址和公司地址等。对于公司,useType 可以为总部、发行中心等等。

businessServices 元素将列出已与 businessEntity 关联的任何服务。由于 Gene 尚未添加任何服务,故而此元素通常为空。最后两项 identifierBagcategoryBag 提供了有关公司本身的其他信息,以便进行搜索。我们稍后将对二者分别进行分析。





回页首


publisherAssertion

publisherAssertionbusinessEntity 之间的关系声明。例如,Francis 知道此项目的目标之一是使用 Daily Star 中提供的服务,其中,Daily Star 将为 Daily Moon 提供体育赛事比分。这使得 Daily Star 成为 Daily Moon 的内容提供者。Francis 可以按照清单 3 中所示的方式表示此关系。


清单 3. publisherAssertion
                    
<publisherAssertion>
<fromKey>(businessKey for Daily Star)</fromKey>
<toKey>(businessKey for Daily Moon)</toKey>
<keyedReference tModelKey="904BD800-D53A-11DA-B055-850A1DA99D79" 
         keyName="optional" keyValue="CONTENTPROVIDER" />
</publisherAssertion>

fromKeytoKey 元素表示所涉及的两个实体的唯一 ID。在本例中,这两个实体指 Daily MoonDaily StarDaily StarDaily Moon 的内容提供者,故而据此放置二者的键。keyedReference 将会多次出现。在本例中,我们可以说引用本身就是内容提供者。keyValuekeyedReference 的唯一必需属性,但常常也会包含 keyName(为了提高可读性)和 tModelKey(标识特定的引用类型)。在本例中,tModelKey 表示两个报社之间关联的命名空间(与内部关系相对)。我们稍后将对 tModels 进行进一步的讨论。





回页首


businessService

接下来,Francis 需要输入有关 Daily Moon 将要提供的任何实际服务的信息。除了所需的唯一 serviceKey 和名称外,businessService 对象中还包含两条重要信息。即 bindingTemplates 和服务所属的任何类别。请参见清单 4。


清单 4. businessService
												
														<businessService serviceKey="required"
												 businessKey="optional">
<name></name>
<description></description>
<bindingTemplates>
<bindingTemplate serviceKey="optional" bindingKey="required">
         ...
</bindingTemplate>
</bindingTemplates>
<categoryBag>
      ...
</categoryBag>
</businessService>





回页首


BindingTemplate

Tmodelinstancedetails 指示其兼容的应用程序或规范。请参见清单 5。


清单 5. bindingTemplate
												
														<bindingTemplate
												 serviceKey="optional"
 bindingKey="required">
                    <accessPoint> OR <hostingRedirector bindingKey="another
 binding to be used instead">
<tModelInstanceDetails>
<tModelInstanceDetail>
<tModelInstanceInfo tModelKey=""uuid key for specification tModel">>
<description></description>
<instanceDetails>
<description></description>
<overviewDoc>
<description></description>
<overviewURL></overviewURL>
</overviewDoc>
<instanceParams>string</intstanceParms>
</instanceDetails>
</tModelInstanceInfo>
<tModelInstanceInfo>
            ...
</tModelInstanceInfo>
  </tModelInstanceDetail> <tModelInstanceDetails> </bindingTemplate>
TModels (including tModel of tModels)
Serve two purposes.  As specification indicators, and as namespace indicators.
<tModel tModelKey="required" operator="optional" 
authorizedName="optional">
<name></name>
<description></description>
<overviewDoc>
<description></description>
<overviewURL></overviewURL>
<overviewDoc>

   <identifierBag>
...
</identifierBag>
<categoryBag>
      ...
</categoryBag>
</tModel>

bindingTemplate 定义在何处能找到服务以及其执行什么工作,这听起来并不复杂。不过,这两项功能在 UDDI 上下文中担任了新的重要角色。例如,为了确定可以在何处访问服务,可以提供 accessPoint(表示简单的 URL)或任何其他相应的数据,如求助热线的号码或 hostingRedirector

分类法

对信息进行分类时,如果能就如何进行分类达成一致则很有帮助。这些一致同意的分类标准称为分类法。

例如,北美工业分类系统 (NAICS) 通过为每种类别指定一个唯一代码来区分“体育用品出租”、“体育用品商店”和“二手体育用品商店”。这样,当遇到代码 532292 时,就知道所说的是出租体育用品的商家,而不是出售这些东西的商家。

UDDI 操作员向系统添加一系列分类法作为例行规定,可供您在无需为其注册 tModels 的情况下使用。例如,jUDDI 可以使用 tModelA035A07C-F362-44DD-8F95-E2B134BF43B4uddi-org:general_keywords 创建 tModel,因此您可以使用它,而不必自己定义。

当服务的绑定发生更改时,将使用 hostingRedirector。例如,如果 Daily Moon 要建立自己的分类广告服务,并允许这两家报社使用 createNewAdd() 调用提交广告,则需要确保服务永远不会更改,或者提供一个方法来告知客户机服务已发生更改。而这就是要使用 hostingRedirector 的地方。在这种情况下,Francis(或实际由 Gene 进行)将创建一个新 bindingTemplate,用于表示新信息,并将该 bindingTemplatebindingKey 输入 hostingRedirector 元素的 bindingKey 属性中。

定义服务能进行的工作可能会更困难。这个原因是两方面的。首先,由于我们讨论的并不一定是 SOAP 服务,因此无法直接为其提供 WSDL 文件。其次,由于这应该是一个自动化过程,因此需要以无歧义的方式提供此信息。

这样所得的结果是一个包括 tModelInstanceDetails 元素的 bindingTemplate,而此元素中又包含一个或多个 tModelInstanceDetail 元素。每个 tModelInstanceDetail 元素又包含一个或多个 tModelInstanceInfo 元素,而后者各自指向一个特定的 tModel。我们稍后将对 tModels 进行讨论。不过,重要的是要理解,tModelInstanceInfo 元素可以包含一个 instanceDetails 元素,后者本身包含一个 overviewDoc,其中包括 overviewURL,即实际定义服务的文档的 URL。(是的,就是在此处指定 WSDL 文件。)





回页首


TModels(包括 tModels 的 tModel)

现在让我们讨论一下 tModels

tModels 实际有两个用途。第一,就是我们在关于 publisherAssertions 的讨论中了解到的,作为“命名空间指示符”。也就是说,tModel 可以提供用于区分很容易混淆的信息类型的方法。经常给出的一个例子是税码(或其他很容易混淆的数字)。例如,包含以下内容的 keyedReference 并不会提供所有信息,因为这两个税务 ID 属于不同的国家。它们在两个国家里都称为税务 ID,但就编程而言,我们必须提供一个区分二者的方法,如清单 6 中所示。


清单 6. 来自不同国家的税务 ID
                    
<keyedReference tModelKey="" keyName="taxid" 
keyValue="11111111" />
<keyedReference tModelKey="" keyName="taxid" 
keyValue="22222222" />

这就是要使用 tModel 的地方。我们可以为“美国税码”创建一个键模型,再为“墨西哥税码”创建一个键模型,依此类推。创建了这些模型后,可以使用其 tModel 键来进一步限定这些 keyedReference。请参见清单 7。


清单 7. tModels 和 keyedReferences
                    
<tModel tModelKey="902CDE50-D53A-11DA-B055-A74C17FA61A7">
   <name>United States codes</name>
</tModel>
<tModel tModelKey="062377D0-D5F5-11DA-8170-8ACF057FECAD">
   <name>Mexico codes</name>
</tModel>
<keyedReference tModelKey="902CDE50-D53A-11DA-B055-A74C17FA61A7" 
                keyName="taxid" keyValue="11111111" />
<keyedReference tModelKey="062377D0-D5F5-11DA-8170-8ACF057FECAD" 
                keyName="taxid" keyValue="22222222" />

tModel 的另一个用途是作为规范标识符。例如,Francis 知道 Gene 将为上个月所处理的 ClassifiedService 创建相应的条目。此服务表示特定的接口,因此可以使用 tModel 对其进行标识。tModel 可能与清单 8 中所示类似。


清单 8. tModel
												
														<tModel tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A"
												 
        operator="optional" authorizedName="optional">

   <name>Classified Service Interface</name>
   <description></description>

   <overviewDoc>
      <description></description>
      <overviewURL>
        http://www.daily-moon.com/ClassifiedService-interface.wsdl
      </overviewURL>
   <overviewDoc>

   <identifierBag>
...
   </identifierBag>

   <categoryBag>
      ...
   </categoryBag>
</tModel>

和我们所讨论的各个其他对象一样,tModel 具有一个唯一键,这是它唯一必需的信息。不过,在本例中,我们还要指定 overviewURL,即接口的 WSDL 文件的 URL。(我们将在后面部分创建它。)

同样,可以使用 identifierBagtModels 进行标识,还可以使用 categoryBag 对其进行归类。接下来让我们看一看如何进行此工作。





回页首


identifierBag

由于 UDDI 设计十分灵活,因此没有特定的方式来标识 businessEntity。UDDI 并不强制要求使用其 D-U-N-S 编号、其税务 ID 编号或任何特定的标识方法对公司进行标识。相反,它提供了一个容器,可以根据需要在其中放置任意数量的标识符,如清单9 中所示。


清单 9. indentifierBag
												
														<identifierBag>
												
												
														<keyedReference
												
 tModelKey="4064C064-6D14-4F35-8953-9652106476A9" 
         keyName="DUNS Number" keyValue="55555555" /><keyedReference tModelKey="" 
         keyName="US Tax ID" keyValue="111111111" /> </identifierBag>

identifierBag 中添加的每个 keyedReference 都代表用户在搜索中找到相关对象的另一个机会。





回页首


categoryBag

categoryBag 的工作方式与 identifierBag 类似,因为其中包含一个或多个 keyedReferences。请参见清单 10。


清单 10. categoryBag
												
														<categoryBag> <keyedReference
												 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" /> </categoryBag>

在本例中,Francis 创建了一个 categoryBag,指示 Daily Moon 是一个报社分支机构。现在让我们了解如何使用所有这些对象。





回页首


将 WSDL 映射到 UDDI

在 Gene 编写任何代码将所有这些信息发送到 UDDI 注册中心前,他必须在其当前服务和 UDDI 之间建立一个重要的联系。他必须对其进行调整,以适应 UDDI 的服务、接口和绑定模板概念。

服务与接口

您可能还记得,服务在 UDDI 中包含三个部分:接口(使用 tModels 定义)、businessServicebindingTemplate(用于将两者捆绑在一起)。因此,Gene 将首先确定用于定义 SOAP 服务的 WSDL 文件如何适应此结构。

他首先对 WSDL 进行分析。幸运的是,这非常简单。除了实现本身外,其余所有 WSDL 内容都属于接口。请参见清单 11。


清单 11. WSDL 接口
                    
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
      xmlns:tns="http://ws.apache.org/axis2"
      xmlns:axis2="http://ws.apache.org/axis2"
      xmlns:ns1="http://org.apache.axis2/xsd" 
      targetNamespace="http://ws.apache.org/axis2">

   <wsdl:types>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
            targetNamespace="http://org.apache.axis2/xsd" 
            elementFormDefault="unqualified" 
            attributeFormDefault="unqualified">

         <xs:element type="ns1:ClassifiedAd" name="ClassifiedAd"
 />
         <xs:complexType name="ClassifiedAd">
            <xs:sequence>
               <xs:element type="xs:int" name="id" />
               <xs:element type="xs:string" name="content" />
               <xs:element type="xs:string" name="endDate" />
               <xs:element type="xs:string" name="startDate" />
            </xs:sequence>
         </xs:complexType>
         ...
      </xs:schema>
   </wsdl:types>

   <wsdl:message name="createNewAdRequestMessage">
      <wsdl:part name="part1" element="ns1:createNewAdRequest" />
   </wsdl:message>
   <wsdl:message name="createNewAdResponseMessage">
      <wsdl:part name="part1" element="ns1:createNewAdResponse" />
   </wsdl:message>
   ...

   <wsdl:portType name="ClassifiedServicePortType">
      <wsdl:operation name="finalizeIssue">
         <wsdl:input message="tns:finalizeIssueRequestMessage" />
      </wsdl:operation>
      <wsdl:operation name="createNewAd">
         <wsdl:input message="tns:createNewAdRequestMessage" />
         <wsdl:output message="tns:createNewAdResponseMessage" />
      </wsdl:operation>
      ...
   </wsdl:portType>

   <wsdl:binding name="ClassifiedServiceBinding" 
                  type="tns:ClassifiedServicePortType">
      <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
                  style="document" />
      <wsdl:operation name="createNewAd">
         <soap:operation soapAction="createNewAd" style="document"
 />
         <wsdl:input>
            <soap:body use="literal" 
                        namespace="http://ws.apache.org/axis2" />
         </wsdl:input>
         <wsdl:output>
            <soap:body use="literal" 
                        namespace="http://ws.apache.org/axis2" />
         </wsdl:output>
      </wsdl:operation>
      ...
   </wsdl:binding>
</wsdl:definitions>

这包括类型定义(XML 模式)、任何消息、portType 甚至 binding,因为绑定并不是特定于实现的。

实现由实际的服务元素组成。请参见清单 12。


清单 12. 服务实现 WSDL
                    
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
      xmlns:tns=
        "http://www.daily-moon.com/ClassifiedService-interface"
      xmlns:axis2="http://ws.apache.org/axis2"
      xmlns:ns1="http://org.apache.axis2/xsd" 
      targetNamespace=
        "http://www.daily-moon.com/ClassifiedService-interface">

<wsdl:import namespace="http://ws.apache.org/axis2" 
   location=
"http://www.nicholaschase.com/ClassifiedService-interface.wsdl" 
/>

<wsdl:service name="ClassifiedService">
   <wsdl:port name="ClassifiedServicePort" 
               binding="axis2:ClassifiedServiceBinding">
      <soap:address 
         location=
 "http://www.daily-moon.com:8080/axis2/services/ClassifiedService" 
      />
   </wsdl:port>
</wsdl:service>

</wsdl:definitions>

请注意,实现文件导入了接口文件。也就是说,此文件是服务的完整定义。

现在让我们来看一看这如何与我们的 UDDI 对象对应。





回页首


将接口映射到 tModel

Gene 首先必须将接口映射到相应的 tModel。请参见清单 13。


清单 13. tModel
                    
<tModel tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">

  
 <name>http://www.daily-moon.com/ClassifiedService-
interface</name>
   <description>Interface for the Daily Moon Classified 
Department web application</description>

   <overviewDoc>
      <description>WSDL interface document</description>
      <overviewURL>
          http://www.daily-moon.com/ClassifiedService-interface.wsdl
      </overviewURL>
   <overviewDoc>

   <categoryBag>
      <keyedReference
 tModelKey="C1ACF26D-9672-4404-9D70-39B756E62AB4"
               keyName="uddi-org:types" keyValue="wsdlSpec" />
      <keyedReference
 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
               keyName="ntis-gov:naics:1997" keyValue="511110" />
   </categoryBag>
</tModel>

首先看最下面,请注意 categoryBag。Gene 添加了两个 keyReferences。第一个指定我们事实上在处理 WSDL 文件。已预定义了特定的 tModelKey 来表示 uddi-org:types 命名空间。所有 WSDL 文件都必须采用这种方式指定。第二个引用绑定到 ntis-gov:naics:1997 命名空间,因此 Gene 的用户可以方便地在表示与报纸有关的服务的所有 WSDL 文件中找到此定义。继续往上,我们可以看到 overviewDoc。除了可选描述外,它还指定了实际的 URL,可以在此处找到 WSDL 文件。

最后,tModel 的名称应与 WSDL 文件的目标命名空间匹配。





回页首


将实现映射到绑定模板

Gene 接下来必须将实现本身映射到 bindingTemplate。请参见清单 14。


清单 14. bindingTemplate
                    
<bindingTemplate serviceKey="" bindingKey="">

   <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
   </accessPoint>

   <tModelInstanceDetails>
      <tModelInstanceDetail>
         <tModelInstanceInfo 
                 tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">
            <instanceDetails>
               <description>The canonical implementation of 
                  the Daily Moon's classified
 service.</description>
               <overviewDoc>
                  <overviewURL>
           http://www.daily-moon.com/ClassifiedService-impl.wsdl
                  </overviewURL>
               </overviewDoc>
            </instanceDetails>
         </tModelInstanceInfo>
      </tModelInstanceDetail>
   </tModelInstanceDetails>


</bindingTemplate> 

这里我们看到,Gene 创建了一个新 bindingTemplate,并将 accessPoint 设置为实际服务的 URL。键 modelInstanceDetails 将接口 tModel(通过 tModelKey)链接到实现文档(在 overviewDoc 中指定)。现在他只需要从服务引用它即可。





回页首


从 businessService 和 businessEntity 引用 bindingTemplate

最后一步是将所有这些组装起来,并从 businessService 引用 bindingTemplate、从 businessEntity 引用 businessService。请参见清单 15。


清单 15. 完整的 businessEntity
                    
<businessEntity businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
   <name>The Daily Moon</name>
   <name lang="fr-ca">La Lune Quotidienne</name>
   <contacts>
      <contact>
         <personName>Pat Mooney</personName>
         <email>[email protected]</email>
      </contact>
   </contacts>

   <businessServices>
      <businessService 
            serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7">
         <name>ClassifiedService</name>
         <bindingTemplates>
            <bindingTemplate 
                 bindingKey="904BD800-D53A-11DA-B055-850A1DA99D79">
               <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
               </accessPoint>

               <tModelInstanceDetails>
                  <tModelInstanceDetail>
                     <tModelInstanceInfo 
                 tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">
                        <instanceDetails>
                           <description>The canonical
 implementation of the Daily Moon's classified 
service.</description>
                           <overviewDoc>
                              <overviewURL>
           http://www.daily-moon.com/ClassifiedService-impl.wsdl
                              </overviewURL>
                           </overviewDoc>
                        </instanceDetails>
                     </tModelInstanceInfo>
                  </tModelInstanceDetail>
               </tModelInstanceDetails>

            </bindingTemplate>
         </bindingTemplates>

         <categoryBag>
            <keyedReference 
                 tModelKey="C1ACF26D-9672-4404-9D70-39B756E62AB4"
                 keyName="uddi-org:types" keyValue="wsdlSpec" />
            <keyedReference 
                 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
                 keyName="ntis-gov:naics:1997" keyValue="511110" />
         </categoryBag>
      </businessService>
   </businessServices>

   <identifierBag>
      <keyedReference
 tModelKey="4064C064-6D14-4F35-8953-9652106476A9" 
         keyName="DUNS Number" keyValue="55555555" />
      <keyedReference tModelKey="" 
         keyName="US Tax ID" keyValue="111111111" />
   </identifierBag>

   <categoryBag>
      <keyedReference
 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" />
   </categoryBag>
</businessEntity>

也就是说,服务现在已经完成:Gene 现在有了一个包含服务的 businessEntity





回页首

你可能感兴趣的:(了解 Web 服务规范: 第 3 部分:统一描述、发现和集成 (UDDI) (2))