Web services提供的服务多种多样,有的可以马上获得结果,有的要消耗很长的时间。所以,如果我们需要多种调用方式来对付不同的情况。
大多数的Web services都提供阻塞(Blocking)和非阻塞(Non-Blocking)两种API。
Blocking API - 调用端要等被调用的函数运行完毕才继续往下走。
Non-Bloking API - 调用端运行完调用函数以后就直接往下走了,调用端和被调用端是异步执行的。返回值是用回调函数来实现的。
这种异步叫做API层异步(API Level Asynchrony)。他们只用到一个连接来发送和接收消息,而且,如果是那种需要运行很长时间的函数,还会碰到Time Out 错误,如果用两个连接分别处理发送和接收消息,调用的时间就可以缩短,也可以解决Time Out 问题。用两个连接来分别处理发送和接收消息,叫做传输层异步(Transport Level Asynchrony)。
将前面的 2 种异步结合起来,就有了四种不同的调用模式
服务的调用代码:
blocking invocation
try { OMElement payload = ClientUtil.getEchoOMElement(); Options options = new Options(); options.setTo(targetEPR); // this sets the location of MyService service ServiceClient serviceClient = new ServiceClient(); serviceClient.setOptions(options); OMElement result = sender.sendReceive(payload); System.out.println(result); } catch (AxisFault axisFault) { axisFault.printStackTrace(); }
IN-ONLY
try { OMElement payload = ClientUtil.getPingOMElement(); Options options = new Options(); options.setTo(targetEPR); ServiceClient serviceClient = new ServiceClient(); serviceClient.setOptions(options); serviceClient.fireAndForget(payload); } catch (AxisFault axisFault) { axisFault.printStackTrace(); }
EchoBlockingClient
将第一段代码的调用代码改为 serviceClient.sendReceiveNonblocking(payload, callback); 具体的例子在 "Axis2Home/samples/userguide/src/userguide/clients" 中
Axis 提供三个方法来接收 callback 对象
public abstract void onComplete(AsyncResult result); public abstract void onError(Exception e); public boolean isComplete() {}
其中,前面两个是需要用户来实现的
try { OMElement payload = ClientUtil.getEchoOMElement(); Options options = new Options(); options.setTo(targetEPR); options.setAction("urn:echo"); //Callback to handle the response Callback callback = new Callback() { public void onComplete(AsyncResult result) { System.out.println(result.getResponseEnvelope()); } public void onError(Exception e) { e.printStackTrace(); } }; //Non-Blocking Invocation sender = new ServiceClient(); sender.setOptions(options); sender.sendReceiveNonBlocking(payload, callback); //Wait till the callback receives the response. while (!callback.isComplete()) { Thread.sleep(1000); } } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } finally { try { sender.cleanup(); } catch (AxisFault axisFault) { // } }
EchoNonBlockingDualClient
try { OMElement payload = ClientUtil.getEchoOMElement(); Options options = new Options(); options.setTo(targetEPR); options.setTransportInProtocol(Constants.TRANSPORT_HTTP); options.setUseSeparateListener(true); options.setAction("urn:echo"); // this is the action mapping we put within the service.xml //Callback to handle the response Callback callback = new Callback() { public void onComplete(AsyncResult result) { System.out.println(result.getResponseEnvelope()); } public void onError(Exception e) { e.printStackTrace(); } }; //Non-Blocking Invocation sender = new ServiceClient(); sender.engageModule(new QName(Constants.MODULE_ADDRESSING)); sender.setOptions(options); sender.sendReceiveNonBlocking(payload, callback); //Wait till the callback receives the response. while (!callback.isComplete()) { Thread.sleep(1000); } //Need to close the Client Side Listener. } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } finally { try { sender.finalizeInvoke(); } catch (AxisFault axisFault) { //have to ignore this } }
在 Server 端添加 Addressing 支持的方式是,在 Addressing Module 中,将 Handlers 的描述放在 ”pre-dispatch” 语句中,那么它的加载则需要通过在 "/webapps/axis2/WEB-INF" 文件夹下的 axis2.xml 中增加一句话来完成: <module ref="addressing"/>
客户端支持 Addressing 的方式,一种是将 addressing-<version>.mar 放在 classpath 中,另一种就是根据给定的库位置创建一个 ConfigurationContext
具体的做法是在 sender = new ServiceClient(); 之前加上
ConfigurationContext configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(< Axis2RepositoryLocation >, null);
然后将 "sender = new ServiceClient();" 改为 "sender = new ServiceClient(configContext, null);"
(五):HelloWorld二改进版(ADB)
1:要想使用Axis2 Databinding Framework (ADB),首先需要根据WSDL来生成在服务端的skeleton文件。进入cmd,设置路径到工程的根下面,运行如下语句:
WSDL2Java -uri classes\META-INF\StockQuoteService.wsdl -p samples.quickstart.service.adb -d adb -s -ss -sd -ssi -o build\service
运行完成后,会生成一个build的文件夹,里面有很多生成的东西。
其中:-d:表示是adb;
-s:表示是同步调用;
-ss:表示创建服务端的代码(包括skeleton和相关文件);
-sd:表示创建services.xml;
-ssi:表示为skeleton创建接口;
2:然后就需要开发人员去实现skeleton的接口了,实现类的架子已经生成了,只要去实现就好了,当然,需要将build\service\src的文件夹添加到Eclipse中工程的源代码来源中。实现类如下:
package samples.quickstart.service.adb; import java.util.HashMap; import samples.quickstart.service.pojo.*; public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface { private static HashMap map = new HashMap(); public void update(Update param0) { map.put(param0.getSymbol(), new Double(param0.getPrice())); } public GetPriceResponse getPrice(GetPrice param1) { Double price = (Double) map.get(param1.getSymbol()); double ret = 42; if (price != null) { ret = price.doubleValue(); } GetPriceResponse res = new GetPriceResponse(); res.set_return(ret); return res; } }
3:客户端的Stub也同样需要生成,进入cmd,设置路径到工程的根下面,运行如下语句:
WSDL2Java -uri classes\META-INF\StockQuoteService.wsdl -p samples.quickstart.clients -d adb -s -o build\client
运行完成后,会生成一个build的文件夹,里面有client文件夹。
需要将build\ client\src的文件夹添加到Eclipse中工程的源代码来源中。
4:同样需要services.xml文件来描述,如下:
<service name="StockQuoteService" scope="application"> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="samples.quickstart.service.adb.StockQuoteServiceMessageReceiverInOut"/> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="samples.quickstart.service.adb.StockQuoteServiceMessageReceiverInOnly"/> </messageReceivers> <parameter name="ServiceClass">samples.quickstart.service.adb.StockQuoteServiceSkeleton </parameter> <operation name="update" mep="http://www.w3.org/2004/08/wsdl/in-only"> <actionMapping>urn:update</actionMapping> </operation> <operation name="getPrice" mep="http://www.w3.org/2004/08/wsdl/in-out"> <actionMapping>urn:getPrice</actionMapping> <outputActionMapping>http://quickstart.samples/StockQuoteServicePortType/getPriceResponse</outputActionMapping> </operation> </service>
5:然后写客户端来调用服务,客户端如下:
package samples.quickstart.service.adb; import samples.quickstart.clients.StockQuoteServiceStub; public class Client { public static void main(java.lang.String args[]){ try{ StockQuoteServiceStub stub = new StockQuoteServiceStub ("http://localhost:8080/axis2/services/StockQuoteService"); getPrice(stub); update(stub); getPrice(stub); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } } /* fire and forget */ public static void update(StockQuoteServiceStub stub){ try{ StockQuoteServiceStub.Update req = new StockQuoteServiceStub.Update(); req.setSymbol ("ABC"); req.setPrice (42.35); stub.update(req); System.err.println("price updated"); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } } /* two way call/receive */ public static void getPrice(StockQuoteServiceStub stub){ try{ StockQuoteServiceStub.GetPrice req = new StockQuoteServiceStub.GetPrice(); req.setSymbol("ABC"); StockQuoteServiceStub.GetPriceResponse res = stub.getPrice(req); System.err.println(res.get_return()); } catch(Exception e){ e.printStackTrace(); System.err.println("\n\n\n"); } } }
6:跟ADB的方式类似的还有:XMLBeans、JiBX进行服务邦定的方式,都是通过WSDL2Java来生成服务端的Skeleton和客户端的Stub,还有相应的接口和实现的架子,具体的服务和客户端的调用还是需要开发人员来写的。
五:认识Axis2
Axis2是什么?
Apache Axis2 是Axis的后续版本,是新一代的SOAP引擎。Axis2是通过用Java语言开发Web Service的工具,Axis2封装了SOAP消息的处理,同时还有做了其他的大量的工作来简化Web Sercice的开发者的工作。
Axis2能做什么?
Axis2的主要特点有:
(1)提供了一个处理SOAP消息的框架,这个框架是极易扩展的,用户可以在每个服务或操作上扩展它。用户也可以在这个框架的基础上对不同的消息交换模型(Message Exchange Patterns)MEPs进行建模
(2)采用名为 AXIOM(AXIs Object Model)的新核心 XML 处理模型,利用新的XML解析器提供的灵活性按需构造对象模型。
(3)支持不同的消息交换模式。目前Axis2支持三种模式:In-Only、Robust-In和In-Out。In-Only消息交换模式只有SOAP请求,而不需要应答;Robust-In消息交换模式发送SOAP请求,只有在出错的情况下才返回应答;In-Out消息交换模式总是存在SOAP请求和应答。
(4)提供阻塞和非阻塞客户端 API。
(5)支持内置的 Web服务寻址 (WS-Addressing)
(6)灵活的数据绑定,可选择直接使用 AXIOM,ADB,或使用 XMLBeans、JiBX 或 JAXB 2.0 等专用数据绑定框架。
(7)新的部署模型,支持热部署,可以用或者不用WSDL来部署
(8)支持HTTP,SMTP,JMS,TCP传输协议。
(9)支持REST (Representational State Transfer)。
(10)提供了代码生成器,可以生成服务器端和客户端的代码
除了上述的这些功能,在内存和速度等性能方面也是Axis2的重点。Axis2的核心框架是构建在WSDL,SOAP和WS-Addressing上,其他的如JAX-RP,SAAJ和WS-Policy是在核心框架之上的层
六:WSDL
1:WSDL 的用途
创建服务时,通常的原因都是因为希望其他人使用此服务。为了使用服务,需要知道向服务发送什么信息、服务将发送回什么信息以及在何处能找到此服务。当然,可以将这些放入字处理文档中,但相比之下,如果此信息采用标准的、最好为人机均可读的格式,则要有用得多。
WSDL 就提供了这样的标准格式。除了不会造成混淆不清外,其主要优势是,由于 WSDL 是事实标准,且采用 XML 格式,因而可由计算机进行处理,便于自动创建客户机(甚至自动创建服务的框架)。
注意这里我们讲述的还是wsdl1.0,但是wsdl2.0已经出来了,2007年推出wsdl2.0。
Wsdl文档结构:
WSDL 文档是利用这些主要的元素来描述某个 web service 的:
<portType>: web service 执行的操作
<message>: web service 使用的消息
<types> :web service 使用的数据类型
<binding> :web service 使用的通信协议
一个 WSDL 文档的主要结构是类似这样的:
<definitions>
<types>
definition of types........
</types>
<message>
definition of a message....
</message>
<portType>
definition of a port.......
</portType>
<binding>
definition of a binding....
</binding>
</definitions>WSDL 文档可包含其它的元素,比如 extension 元素,以及一个 service 元素,此元素可把若干个 web services 的定义组合在一个单一的 WSDL 文档中。
1:<portType> 元素是最重要的 WSDL 元素。它可描述一个 web service、可被执行的操作,以及相关的消息。可以把 <portType> 元素比作传统编程语言中的一个函数库(或一个模块、或一个类)。
2:<message> 元素定义一个操作的数据元素。每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个函数调用的参数。
3:<types> 元素定义 web service 使用的数据类型。为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。
4:<binding> 元素为每个端口定义消息格式和协议细节
WSDL的PortType:
操作类型:WSDL中定义了四种类型:
One-way :此操作可接受消息,但不会返回响应。
Request-response: 此操走可接受一个请求并会返回一个响应
Solicit-response :此操作可发送一个请求,并会等待一个响应。
Notification :此操作可发送一条消息,但不会等待响应。
1:一个 one-way 操作的例子:
<message name="newTermValues"> <part name="term" type="xs:string"/> <part name="value" type="xs:string"/> </message> <portType name="glossaryTerms"> <operation name="setTerm"> <input name="newTerm" message="newTermValues"/> </operation> </portType >
2:一个 request-response 操作的例子:
<message name="getTermRequest"> <part name="term" type="xs:string"/> </message> <message name="getTermResponse"> <part name="value" type="xs:string"/> </message> <portType name="glossaryTerms"> <operation name="getTerm"> <input message="getTermRequest"/> <output message="getTermResponse"/> </operation> </portType>
WSDL的绑定:
绑定到 SOAP
一个请求 - 响应操作的例子:
<message name="getTermRequest"> <part name="term" type="xs:string" /> </message> <message name="getTermResponse"> <part name="value" type="xs:string" /> </message> <portType name="glossaryTerms"> <operation name="getTerm"> <input message="getTermRequest" /> <output message="getTermResponse" /> </operation> </portType> <binding type="glossaryTerms" name="b1"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <operation> <soap:operation soapAction="http://example.com/getTerm" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding>
binding 元素有两个属性 - name 属性和 type 属性。
name 属性定义 binding 的名称,而 type 属性指向用于 binding 的端口,在这个例子中是 "glossaryTerms" 端口。
soap:binding 元素有两个属性 - style 属性和 transport 属性。
style 属性可取值 "rpc" 或 "document"。在这个例子中我们使用 document。transport 属性定义了要使用的 SOAP 协议。在这个例子中我们使用 HTTP。
operation 元素定义了每个端口提供的操作符。
对于每个操作,相应的 SOAP 行为都需要被定义。同时您必须如何对输入和输出进行编码。在这个例子中我们使用了 "literal"。
例子:
下面是前面的HelloWorld生成的wsdl文件:
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns="http://pojo.service.quickstart.samples" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://pojo.service.quickstart.samples"> <wsdl:types> <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://pojo.service.quickstart.samples"> <xs:element name="getPrice"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="symbol" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="getPriceResponse"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:double"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="update"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="symbol" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="price" type="xs:double"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> </wsdl:types> <wsdl:message name="getPriceRequest"> <wsdl:part name="parameters" element="ns:getPrice"/> </wsdl:message> <wsdl:message name="getPriceResponse"> <wsdl:part name="parameters" element="ns:getPriceResponse"/> </wsdl:message> <wsdl:message name="updateRequest"> <wsdl:part name="parameters" element="ns:update"/> </wsdl:message> <wsdl:portType name="StockQuoteServicePortType"> <wsdl:operation name="getPrice"> <wsdl:input message="ns:getPriceRequest" wsaw:Action="urn:getPrice"/> <wsdl:output message="ns:getPriceResponse" wsaw:Action="urn:getPriceResponse"/> </wsdl:operation> <wsdl:operation name="update"> <wsdl:input message="ns:updateRequest" wsaw:Action="urn:update"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="StockQuoteServiceSoap11Binding" type="ns:StockQuoteServicePortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="getPrice"> <soap:operation soapAction="urn:getPrice" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="update"> <soap:operation soapAction="urn:update" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:binding name="StockQuoteServiceSoap12Binding" type="ns:StockQuoteServicePortType"> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="getPrice"> <soap12:operation soapAction="urn:getPrice" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="update"> <soap12:operation soapAction="urn:update" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:binding name="StockQuoteServiceHttpBinding" type="ns:StockQuoteServicePortType"> <http:binding verb="POST"/> <wsdl:operation name="getPrice"> <http:operation location="StockQuoteService/getPrice"/> <wsdl:input> <mime:content type="text/xml" part="getPrice"/> </wsdl:input> <wsdl:output> <mime:content type="text/xml" part="getPrice"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="update"> <http:operation location="StockQuoteService/update"/> <wsdl:input> <mime:content type="text/xml" part="update"/> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:service name="StockQuoteService"> <wsdl:port name="StockQuoteServiceHttpSoap11Endpoint" binding="ns:StockQuoteServiceSoap11Binding"> <soap:address location="http://localhost:8080/axis2/services/StockQuoteService"/> </wsdl:port> <wsdl:port name="StockQuoteServiceHttpSoap12Endpoint" binding="ns:StockQuoteServiceSoap12Binding"> <soap12:address location="http://localhost:8080/axis2/services/StockQuoteService"/> </wsdl:port> <wsdl:port name="StockQuoteServiceHttpEndpoint" binding="ns:StockQuoteServiceHttpBinding"> <http:address location="http://localhost:8080/axis2/services/StockQuoteService"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
七:SOAP
1:简单的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>
2:soap信封
Web 服务消息的基本单元是实际的 SOAP 信封。这是包含处理消息所必需的所有信息的 XML 文档
<?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>
3:soap的Header
SOAP 消息中的 Header 用于提供有关消息本身的信息,与用于应用程序的信息相对。例如,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 可以提供许许多多的功能(如果您需要)即可。
4:soap的Body
发送 SOAP 消息时,都是有目的性的。您在尝试告诉接收者执行某种操作,或尝试向服务器传递相关信息。此信息称为“有效负载”。有效负载位于 Envelope 的 Body 中。它还具有自己的命名空间,在本例中其命名空间与内容管理系统对应。在此情况下,可以完全随意地选择命名空间。只需要与 SOAP 命名空间相异即可
<?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 的内容管理系统的指令。
4:样式和编码
这个主要是在WSDL(Web服务描述语言)中讲述。
简单来说,有两种不同的主流 SOAP消息编程样式。第一种是 RPC 样式,基于使用 SOAP 消息创建远程过程调用(Remote Procedure Call)的概念。在此样式中,基本思路是在向服务器发送命令(如“添加文章”),并将该命令的参数(如要添加的文章和应该添加到的类别)作为整个方法的子元素包含在其中
[code]
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">
<env:Header> [/code]
RPC 样式的替代方法将数据直接作为 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>
第二个样式称为 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 样式,但目前还没有人这样做,因此可以将其忽略。
5:消息交换模式
发送消息,就实质而言,只有两个选择:
请求/响应:在请求/响应模式种,以 SOAP 消息的形式发送请求,然后直接等待发送回响应。请求可以为同步的,也可以是异步的。
单向消息传递:这种情况也称为“Fire and Forget”方法,发送请求但并不等待响应。可以在仅传递信息时或并不关心接收者对此如何响应时使用此方法。