为了使对web服务的讨论更加有趣,我们先看一个实际的例子:Amazon的web服务,在http://www. amazon.com/gp/aws/landing.html有其描述。这个电子商务web服务使程序员可以按自己所需与Amazon系统进行交互。举例来说,你可以指定作者或书名,从而列出所有相关书籍,也可以填满购物车然后下订单。Amazon使这样的服务成为可能,于是那些想把东西卖给顾客的公司都可以使用它,将Amazon的系统作为实现的后台。要运行我们的例子,必须到Amazon注册,以取得一个免费的开发者令牌,有了它才可以连接该服务。
或者,你可以采用本节描述的技巧,应用于其他的web服务。http://www.xmethods.com网站列出了许多免费可用的web服务。
让我们更仔细地看看Amazon的E-Commerce服务的WSDL(位于http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl),它描述了一个ItemSearch操作:
<operation name="ItemSearch">
<input message="tns:ItemSearchRequestMsg"/>
<output message="tns:ItemSearchResponseMsg"/>
</operation>...<message name="ItemSearchRequestMsg">
<part name="body" element="tns:ItemSearch"/>
</message>
<message name="ItemSearchResponseMsg">
<part name="body" element="tns:ItemSearchResponse"/>
</message>
下面是ItemSearch和ItemSearchResponse类型的定义:
<xs:element name="ItemSearch">
<xs:complexType>
<xs:sequence>
<xs:element name="MarketplaceDomain" type="xs:string" minOccurs="0"/>
<xs:element name="AWSAccessKeyId" type="xs:string" minOccurs="0"/>
<xs:element name="SubscriptionId" type="xs:string" minOccurs="0"/>
<xs:element name="AssociateTag" type="xs:string" minOccurs="0"/>
<xs:element name="XMLEscaping" type="xs:string" minOccurs="0"/>
<xs:element name="Validate" type="xs:string" minOccurs="0"/>
<xs:element name="Shared" type="tns:ItemSearchRequest" minOccurs="0"/>
<xs:element name="Request" type="tns:ItemSearchRequest" minOccurs="0"
maxOcurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ItemSearchResponse">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:OperationRequest" minOccurs="0"/>
<xs:element ref="tns:Items" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
通过使用JAX-WS技术,ItenSearch操作就变成了一个方法调用:
void itemSearch(String marketPlaceDomain, String awsAccessKeyId,
String subscriptionId, String associateTag, String xmlEscaping, String validate,
ItemSearchRequest shared, List<ItemSearchRequest> request,
Holder<OperationRequest> opHolder, Holder<List<Items>> responseHolder)
ItemSearchRequest参数类型定义如下:
<xs:complexType name="ItemSearchRequest">
<xs:sequence>
<xs:element name="Actor" type="xs:string" minOccurs="0"/>
<xs:element name="Artist" type="xs:string" minOccurs="0"/>
. . .
<xs:element name="Author" type="xs:string" minOccurs="0"/>
. . .
<xs:element name="ResponseGroup" type="xs:string"
minOccurs="0" maxOccurs="unbounded"/>
. . .
<xs:element name="SearchIndex" type="xs:string" minOccurs="0"/>
. . .
</xs:complexType>
这个描述被转译成了一个类:
public class ItemSearchRequest
{
public ItemSearchRequest() { ... }
public String getActor() { ... }
public void setActor(String newValue) { ... }
public String getArtist() { ... }
public void setArtist(String newValue) { ... }
...
public String getAuthor() { ... }
public void setAuthor(String newValue) { ... }
...
public List<String> getResponseGroup() { ... }
...
public void setSearchIndex(String newValue) { ... }
...
}
要调用该查询服务,就要构造一个ItemSearchRequest对象,然后调用一个"port"对象的itemSearch方法。
ItemSearchRequest request = new ItemSearchRequest();
request.getResponseGroup().add("ItemAttributes");
request.setSearchIndex("Books");
Holder<List<Items>> responseHolder = new Holder<List<Items>>();
request.setAuthor(name);
port.itemSearch("", accessKey, "", "", "", "", request, null, null, responseHolder);
port类是自动生成的。port对象将Java对象翻译成SOAP消息,并将此消息传递给Amazon服务器,然后将返回的消息翻译为一个ItemSearchResponse对象,将响应置于"持有器"对象中。
注意
Amazon关于参数和返回值的文档写得异常简要。但是,你可以填充http://awszone.com/scratchpads/index.aws处的表格,以查看SOAP请求和响应。这有助于你去猜测需要提供什么样的参数值以及可以得到什么样的返回值。