共享 Web 服务
|
|
|
级别: 中级
Nicholas Chase
(ibmquestions@nicholaschase.com) Backstop Media
2006 年 10 月 19 日
面向服务的体系结构(Service-Oriented Architectures,SOA)当前强调的重点在 Web 服务上,但很容易被所传播的各种信息搞得昏头转向。本系列教程将对主要 Web 服务规范进行全面说明,从简单对象访问协议(Simple Object Access Protocol,SOAP)一直介绍到 WS Business Process Execution Language (WS-BPEL)。在第 2 部分中,您将了解有关 Web 服务描述语言的内容,因为 Daily Moon Classified Department 需要使用 WSDL 来描述其 Web 服务,以便其他人能够方便地从任何编程语言或平台创建客户机访问此服务。
开始之前
本教程旨在帮助您了解 Web 服务描述语言 (Web Services Description Language)。本教程适合希望通过使用 WSDL 公开自己的服务供他人使用的开发人员,同时也适合拥有希望访问的服务的 WSDL 而需要创建客户机的开发人员。
为了学习本教程,您应该具有 SOAP 的基本知识(可以通过阅读本系列教程的第 1 部分了解 SOAP)和 XML 的基本知识。WSDL 与编程语言无关,但本教程最后的示例使用了 Java 和 Apache Axis2 项目。不过,其中的概念也适用于任何编程语言和环境。与此类似,本教程侧重于通常实现的 WSDL 1.1,但即将推出的 WSDL 2.0 的概念也与此相同,本教程将对二者的基本差异进行说明。
关于本系列
本系列教程以假想的报社 Daily Moon 为例,为了提高在竞争激烈的环境中的工作效率,其员工将使用各种 Web 服务来创建工作流系统,我们将在此过程中讲解各个 Web 服务基本概念。
第 1 部分比较简单,说明了 Web 服务背后的基本概念,并演示了如何使用 SOAP(后续教程讨论的大部分内容的基础规范)来将 Classifieds Department 连接到内容管理系统。
在第 2 部分中,Classifieds Department 将开展进一步的工作:使用 Web 服务描述语言 (WSDL) 定义 Web 服务预期产生的消息,从而使团队更方便地创建服务以及连接到服务的客户机。
在第 3 部分中,团队希望准备一系列服务,并希望能方便地查找这些服务。与此对应,统一描述、发现和集成(Universal Description, Discovery and Integration,UDDI)提供了可用服务的可搜索注册中心,以便使自己的服务为其他人所注意。
第 4 部分和第 5 部分讨论 WS-Security 和 WS-Policy,将详细说明如何保证该报社的服务的安全,以及团队为了访问这些刚提供了安全保护的服务需要进行哪些更改。
第 6 部分重点讨论互操作性,因为必须从单个系统访问来自几个不同实现的服务。这一部分还将 WS-I 证书中涉及的要求和测试。
最后,第 7 部分演示如何使用业务流程执行语言(Business Process Execution Language,WS-BPEL)来从各个服务创建复杂应用程序。
接下来让我们更为详细地了解一下本教程中将讨论的内容。
关于本教程
本系列的第 1 部分了解 Web 服务规范:SOAP 介绍了虚构的 Daily Moon 报社。具体来说,您了解了 Classifieds Department 所进行的工作。在该教程中,Classifieds Department 构建了一个客户机来在表示内容管理系统的 Web 服务间发送 SOAP 消息。在本教程中,由于对所看到的结果印象深刻,Classifieds Department 决定构建自己的 Web 服务来接收和管理 classifieds 数据库中的广告。不过,为了允许其他人使用此服务,他们将需要创建 Web 服务描述语言 (WSDL) 文件。此文件将向构建客户机提供说明,以便了解服务预期和返回的消息。
在本教程中,您将了解以下内容:
-
WSDL 文件为何重要
-
可以如何处理 WSDL 文件
-
XML 模式(出现在 WSDL 文件中)的基本知识
-
如何设计 WSDL 文件的结构
-
WSDL 1.1 和 WSDL 2.0 的基本差异
-
如何自动从表示服务的 Java 类自动生成 WSDL 文件
-
如何从 WSDL 文件生成表示服务的 Java 类
-
如何从 WSDL 文件生成 Web 服务客户机
Classifieds Department 将构建一个服务来接收新广告、编辑和显示现有广告,还能结束一个主题,使其不再接受任何广告。他们将同时使用请求/响应和单向消息传递。
工具和先决条件
本教程的大部分内容都是概念性的,但为了处理整个教程中的代码,您将需要安装以下软件:
Apache Geronimo 或其他应用服务器——团队将在本教程中创建新 Web 服务,您将需要可在其上运行服务的应用程序。当然,由于 Web 服务应当可互操作,因此使用何种应用服务器并不重要。本教程演示了 Apache Geronimo 的用法,而此应用服务器也是 IBM 的 WebSphere Community Edition 的基础。还可以使用 WebSphere Application Server 等其他应用服务器。您可以从以下网址下载 Apache Geronimo:http://geronimo.apache.org/downloads.html。有关安装 Geronimo 的更多信息,请参见本系列的第一篇教程“了解 Web 服务规范,第 1 部分:SOAP”。
Apache Axis2 的 0 .95 或更高版本——可以手动创建 SOAP 消息,也可以手动对其进行解释,但手边如果有一个可用实现就会方便得多。本教程将演示 Apache Axis2 的用法,其中包含了各种 SOAP 相关的 API,可极大地简化您的工作。可以从以下网址下载 Apache Axis2:http://ws.apache.org/axis2/download.cgi。本教程使用的是 0.95 版,但应该也能使用更高版本。(请注意,在本系列教程的第 1 部分使用的是 0.94 版,但并未使用该版本对本部分的代码进行测试。)
Java 2 Standard Edition 的 1.4 或更高版本——所有这些工具都是基于 Java 的,本教程中将要构建的服务和客户机也是如此。可以从以下网址下载 J2SE SDK:http://java.sun.com/j2se/1.5.0/download.jsp。
另外,还需要 Web 浏览器和文本编辑器,但我想您已经有了这两个工具。如果愿意,还可以使用 Eclipse 之类的 IDE,但由于我们的重点是技术而不是工具,因此我将使用文本编辑器和命令行来编辑和编译文件。
|
概述
在深入了解细节前,让我们了解一下其总体概貌。
Web 服务回顾
相对于传统编程方法而言,使用 Web 服务的主要优势是互操作性。您可以创建一个分布式系统,让分散在各个位置的计算机能够进行通信,但在大多数情况下,您需要使用限制灵活性的专用中间件。也就是说,发送方和接收方都需要使用相同的软件。
Web 服务提供了基于文本(实际上是基于 XML)的方法来往返传递消息,这意味着应用程序不仅不依赖计算机,而且也不依赖于操作系统和编程语言。只要双方遵循相同的 Web 服务标准,就不受各方运行何种软件的影响。
有多个用于传输此信息的标准,但本系列教程重点讨论的是 SOAP,因为此标准非常灵活,而且能与更高级的标准结合使用。
SOAP 知识巩固
SOAP 消息包括三个主要部分:Header、主体和有效负载(包含在主体中)。请看以下示例:
清单 1. 示例 SOAP 消息
>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<
|
整个消息称为信封,其内容由 Header 和主体组成。Header 包括有关消息本身的信息(如路由信息),或要由位于发送方和最终接收方之间可能对消息进行处理的“SOAP 中间层”或服务处理的信息。消息的主体中包含“有效负载”,其中包含传递给 Web 服务的实际数据。
在本例中,有效负载为 getNumberOfArticles
元素及其内容。
WSDL 的用途
创建服务时,通常的原因都是因为希望其他人使用此服务。为了使用服务,需要知道向服务发送什么信息、服务将发送回什么信息以及在何处能找到此服务。当然,可以将这些放入字处理文档中,但相比之下,如果此信息采用标准的、最好为人机均可读的格式,则要有用得多。
WSDL 就提供了这样的标准格式。除了不会造成混淆不清外,其主要优势是,由于 WSDL 是事实标准,且采用 XML 格式,因而可由计算机进行处理,便于自动创建客户机(甚至自动创建服务的框架)。Classifieds Department 将要创建接受和管理 classified 广告的服务,以允许其他人(如作业聚合网站)能更方便地使用此服务,他们同样也将使用 WSDL 文件对其进行描述。
本教程的任务
在本教程中,您将逐步了解 Daily Moon Classifieds Department 的员工如何创建服务并将其公开给其他人使用,从而了解有关 WSDL 的知识。
首先,Christine 将设计 XML 模式,其中定义可以在 SOAP 消息中出现的数据。接下来,Larry 形成实际 WSDL 文件的结构,以确定将往返传递何种信息。然后,Gene 拿到 WSDL 文件,以其为基础设计表示服务的 Java 类,随后,为了进一步确认,他使用 Axis2 从该 Java 类生成 WSDL 文件,以了解二者的差异。然后,Francis 得到此 WSDL 文件,使用其生成基本 Web 服务和访问该服务的客户机。
现在让我们开始吧。
XML 模式简要介绍
Daily Moon 是一家相当小的报社,因此 Classifieds Department 无法承担专用 DBA 带来的相关支出。所以,Christine 总是将数据库视为“自己的孩子”。了解了 WSDL 的规范后,她决定承担起定义 SOAP 消息中可包含的数据的任务。
验证和选项
在首次尝试 Web 服务之后,员工已经熟悉了 XML,因此 Christine 下一步就要了解有关验证的知识。
XML 验证是确保 XML 的结构和内容符合任何预先定义的要求的过程。最初的时候,这表示要符合文档类型定义(Document Type Definition,DTD);DTD 是从 XML 的前身 SGML 语言保留下来的结构。DTD 并不是很难,但存在一些主要的缺点,缺乏灵活性、缺乏 XML 命名空间支持以及其他问题,因此 XML 社区转而采用其他类型的 XML 模式。
请注意,此处所说的“模式”不是特指的。在这里,我使用的是该术语的一般用法,即文档的具体结构,而不是记录此结构的任何语言。这些 XML 模式的最常见支持是 W3C XML Schema 语言,经常将此语言简称为 XML Schema。(注意首字母大写。)
Christine 知道将使用 XML Schema 构建其 WSDL 1.1 文档,但注意到 WSDL 2.0 还特别支持其他模式,如 RELAX NG 和 Schematron,可以在此处使用这些模式。
实例文档
Christine 首先从一个与进出系统的预期数据近似的示例文档着手。她以数个现有广告为基础创建了以下 XML:
清单 2. 实例文档
Listing 2: the instance document
<?xml version="1.0"?>
<ClassifiedList>
<ClassifiedAd adId="1138">
<content>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.</content>
<endDate>4/15/2007</endDate>
<startDate>4/1/2007</startDate>
</ClassifiedAd>
<ClassifiedAd adId="2187">
<content>30 ft ladder, only used once. Willing to let
go for half its worth. Has slight dent near the middle.
Harder than a human head. $150 OBO.</content>
<endDate>4/30/2007</endDate>
<startDate>4/10/2007</startDate>
</ClassifiedAd>
</ClassifiedList>
|
此文档称为“实例文档”,代表 XML 模式所定义的数据。在本例中,它包括两个作为 ClassifiedList
元素子项的 ClassifiedAd
元素。每个 ClassifiedAd
都包含一个 adId
属性(此属性与数据库内的主键对应)、广告内容以及广告的开始和结束日期。
她将此文档命名为 classifieds.xml
。
基本模式
Christie 下一步将创建基本模式文档,以便对系统进行测试。实际模式本身也是一个 XML 文档,因此她创建了基础文件 classifieds.xsd 和一个 schema 元素,如清单 3 中所示:
清单 3. Schema 元素
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
</xsd:schema>
|
此元素将作为 Christine 创建的所有定义的父项。
验证文档
测试系统的下一步是形成一个简单的 Java 应用程序,以根据模式验证实例文档。该类所需要进行的工作就是指定验证并对文档进行解析,如清单 4 中所示。
清单 4. ValidateWithSchema 类
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class ValidateWithSchema {
public static void main(String args[]) {
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setValidating(true);
dbf.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
dbf.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaSource",
"classifieds.xsd");
Document doc = null;
try{
DocumentBuilder parser = dbf.newDocumentBuilder();
doc = parser.parse("classifieds.xml");
} catch (Exception e){
e.printStackTrace();
}
}
}
|
实际进行解析的方法并不十分重要;在本例中,Christine 将使用 DOM 解析器构建应用程序。首先,构建一个工厂,然后指定其创建的所有解析器都应为“验证解析器”。(并不会使用所有解析器进行验证。有些仅验证文档是否“形式良好”,而不会验证其实际结构。)
接下来,指定要使用的模式语言以及模式文档本身。在本例中,Christine 使用的是本地文件,但也可以使用任何可作为 URL 引用的文件。
Christine 保存文件,并对其进行编译,运行该文件后,她得到了以下输出,如清单 5 中所示。
清单 5. 运行空白模式
Warning: validation was turned on but an org.xml.sax.ErrorHandler
was not set, which is probably not what is desired. Parser will
use a default ErrorHandler to print the first 10 errors. Please call
the 'setErrorHandler' method to fix this.
Error: URI=file:///E:/WSDLFiles/classifieds.xml Line=2: cvc-elt.1:
Cannot find the declaration of element 'ClassifiedList'.
|
Warning
并不重要;Christine 仅希望知道文件是否有效,因此她并不需要任何特定的错误处理功能。Error
很重要,因为这意味着分析器在实际查看模式和验证实例文档。
接下来她需要添加实际的定义。
创建简单的元素
定义最初的数个元素非常简单。content
, endDate
和 startDate
元素包含简单的字符串,如清单 6 中所示。
清单 6. 添加简单的元素
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element type="xsd:string" name="content" />
<xsd:element type="xsd:string" name="endDate" />
<xsd:element type="xsd:string" name="startDate" />
</xsd:schema>
|
在本例中,Christine 定义了三个仅包含文本的元素(与其他元素相对)作为内容。同样,它们都不具有任何属性。XML Schema 推荐标准定义了一系列可用于定义内容的不同类型。例如,可以指定 endDate
和 startDate
值必须为 datetime
类型的值。
创建更为复杂的元素
当然,如果所有元素都这样简单,您可能根本不需要模式了。Christine 将继续定义 ClassifiedList
元素(请参见清单 7)。
清单 7. 定义 ClassifiedList 元素
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="ClassifiedList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ClassifiedAd" maxOccurs="unbounded"
type="ClassifiedAdType"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="ClassifiedAdType">
<xsd:sequence>
<xsd:element type="xsd:string" name="content" />
<xsd:element type="xsd:string" name="endDate" />
<xsd:element type="xsd:string" name="startDate" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
|
首先看最下面,Christine 创建了 ClassifiedAdType complexType
。这种元素类型按顺序包含以下内容:一个 content 元素、一个 endDate
元素和一个 startDate
元素。回到最上面,她定义 ClassifiedList
元素包含一个元素,而此元素还包含一系列元素。不过,在本例中,它包含零个或更多 ClassifiedAdType
类型的元素,所有这些元素均命名为 ClassifiedAd
。
到目前为止,仅通过这两个定义,她就已覆盖了文档结构的大部分。现在需要做的就是为 adId
属性添加定义。
添加属性
属性在 complexType
元素中定义,如清单 8 中所示。
清单 8. 添加属性,不过她还可以创建限制性更多的类型。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="ClassifiedList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ClassifiedAd" maxOccurs="unbounded"
type="ClassifiedAdType"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="ClassifiedAdType">
<xsd:sequence>
<xsd:element type="xsd:string" name="content" />
<xsd:element type="xsd:string" name="endDate" />
<xsd:element type="xsd:string" name="startDate" />
</xsd:sequence>
<xsd:attribute name="adId" type="xsd:integer" />
</xsd:complexType>
</xsd:schema>
|
在本例中,Christine 将 adId
属性的内容限制为整数。不过,她还可以创建限制更多的类型。
使用 simpleTypes
XML Schema 提供了强大的功能,用以处理您的文档可能包含的实际内容。例如,Christine 可以指定 adId
属性一定只能包含大于或等于 1000 的整数(请参见清单 9)。
清单 9. 限制值
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
<xsd:complexType name="ClassifiedAdType">
<xsd:sequence>
<xsd:element type="xsd:string" name="content" />
<xsd:element type="xsd:string" name="endDate" />
<xsd:element type="xsd:string" name="startDate" />
</xsd:sequence>
<xsd:attribute name="adId" type="thousandOrGreater" />
</xsd:complexType>
<xsd:simpleType name="thousandOrGreater">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="1000"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
|
这个定义并不涉及任何元素,因此 Christine 使用了 simpleType
而不是 complexType
。她为定义为整数的基本类型创建了一个 restriction
(一种对数据类型的限制)。她为该 restriction 添加了一个“facet”,指定最小值为 1000。XML Schema 定义了大量的此类 facet 以供使用。创建了此类型后,她就可以在属性定义中对其进行引用了。因为已经定义了数据,Christine 随后将此模式交给 Larry,供他用于构建实际的 WSDL。
posted on 2006-12-29 19:04
SIMONE 阅读(1408)
评论(0) 编辑 收藏 所属分类:
AXIS 、
JAVA