我应该使用哪种wsdl样式?

来源:互联网 发布:创维网络电视怎么放dvd 编辑:程序博客网 时间:2024/06/05 17:35

参考文章

http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?


前言

WSDL 绑定样式可以是 RPC 样式或文档样式。用法可以是编码的,也可以是文字的。您如何决定使用哪一种样式/用法的组合呢?本文将帮助您解决这个问题。

介绍

Web 服务是通过 WSDL 文档来描述的。WSDL 绑定描述了如何把服务绑定到消息传递协议(特别是 SOAP 消息传递协议)。WSDL SOAP 绑定可以是 RPC 样式的绑定,也可以是文档样式的绑定。同样,SOAP 绑定可以有编码的用法,也可以有文字的用法。这给我们提供了四种样式/用法模型:

  1. RPC/编码
  2. RPC/文字
  3. 文档/编码
  4. 文档/文字

除了这些样式之外,还有一种样式也很常见,它称为文档/文字包装的样式,算上这一种,在创建 WSDL 文件时您就有了五种绑定样式可以从中选择。您应该选择哪一种呢?对于本文的讨论,让我们从 清单1中的 Java 方法开始,并且对其应用 JAX-RPC Java-to-WSDL 规则

Listing 1. Java method
public void myMethod(int x, float y);

RPC/编码

采用 清单1中的方法并且使用您喜欢的 Java-to-WSDL 工具来运行它,指定您想让它生成 RPC/编码的 WSDL。您最后应该得到如 清单2所示的 WSDL 片断。

Listing 2. RPC/encoded WSDL for myMethod
<message name="myMethodRequest">    <part name="x" type="xsd:int"/>    <part name="y" type="xsd:float"/></message><message name="empty"/><portType name="PT">    <operation name="myMethod">        <input message="myMethodRequest"/>        <output message="empty"/>    </operation></portType><binding .../>  <!-- I won't bother with the details, just assume it's RPC/encoded. -->

现在用“5”作为参数 的值和5.0作为参数y的值来调用此方法。我们将发送一个与 清单3类似的 SOAP 消息。

Listing 3. RPC/encoded SOAP message for myMethod
<soap:envelope>    <soap:body>        <myMethod>            <x xsi:type="xsd:int">5</x>            <y xsi:type="xsd:float">5.0</y>        </myMethod>    </soap:body></soap:envelope>


对于这个 RPC/编码的示例中的 WSDL 和 SOAP 消息,有许多需要注意的事项:

优点

WSDL 基本达到了尽可能地简单易懂的要求。操作名出现在消息中,这样接收者就可以很轻松地把消息发送到方法的实现。

缺点

类型编码信息(比如 xsi:type="xsd:int" )通常就是降低吞吐量性能的开销。您不能简单地检验此消息的有效性,因为只有<x ...>5</x> and <y ...>5.0</y> 行包含在 Schema 中定义的内容;其余的 soap:body 内容都来自 WSDL定义。不兼容ws-i

RPC/文字

用于我们的方法的 RPC/文字的 WSDL 看起来与 RPC/编码的 WSDL 几乎一样(请参见 清单4)。只是绑定的用法由编码改为文字。

Listing 4. RPC/literal WSDL for myMethod
<message name="myMethodRequest">    <part name="x" type="xsd:int"/>    <part name="y" type="xsd:float"/></message><message name="empty"/><portType name="PT">    <operation name="myMethod">        <input message="myMethodRequest"/>        <output message="empty"/>    </operation></portType><binding .../>  <!-- I won't bother with the details, just assume it's RPC/literal. -->

What about the SOAP message for RPC/literal (see Listing 5)? Here there is a bit more of a change. The type encodings have been removed.

Listing 5. RPC/literal SOAP message for myMethod
<soap:envelope>    <soap:body>        <myMethod>            <x>5</x>            <y>5.0</y>        </myMethod>    </soap:body></soap:envelope>

优点

WSDL 还是基本达到了尽可能地简单易懂的要求,操作名仍然出现在消息中,去掉了类型编码,兼容ws-i。

缺点

您仍然不能简单地检验此消息的有效性,因为只有 <x ...>5</x> and <y ...>5.0</y> 行包含在 Schema 中定义的内容;其余的soap:body 内容都来自 WSDL 定义。


文档/编码

没有人使用这种方式,不兼容ws-i,让我们继续往下。


文档/文字

文档/文字的 WSDL 对 RPC/文字的 WSDL 作了一些更改。它们之间的不同之处显示在 清单6中。

Listing 6. Document/literal WSDL for myMethod
<types>    <schema>        <element name="xElement" type="xsd:int"/>        <element name="yElement" type="xsd:float"/>    </schema></types><message name="myMethodRequest">    <part name="x" element="xElement"/>    <part name="y" element="yElement"/></message><message name="empty"/><portType name="PT">    <operation name="myMethod">        <input message="myMethodRequest"/>        <output message="empty"/>    </operation></portType><binding .../>  <!-- I won't bother with the details, just assume it's document/literal. -->

The SOAP message for this WSDL is in Listing 7:

Listing 7. Document/literal SOAP message for myMethod
<soap:envelope>    <soap:body>        <xElement>5</xElement>        <yElement>5.0</yElement>    </soap:body></soap:envelope>

优点

没有编码信息,您可以在最后用任何 XML 检验器检验此消息的有效性,每项内容都定义在 Schema 中,兼容ws-i,但有限制,见缺点。

缺点

WSDL 变得有些复杂。不过,这是一个非常小的缺点,因为 WSDL 并没有打算由人来读取,SOAP 消息中缺少操作名,而如果没有操作名,发送就可能比较困难,并且有时变得不可能。WS-I 只允许soap消息中的soap:body元素出现一个子元素.,但是你从清单7可以看到,这里出现了2个子元素。

在标准Document/literal 方式下,程序员不得不处理所有的事务,包括基于 XML 的 SOAP 消息的序列化和逆序列化。标准的Document/literal不是面向RPC的,也没有定义与远程调用相关的信息,对仍然酷爱RPC调用的开发者来说无疑是欠缺的,在SOAP工具开发者看来Document/literal标准方式主要是缺乏函数的方法名。

于是微软提出了使用Document/literal模拟RPC的方法调用,定义了一种用特殊的Document/literal使用方法,有名称叫做Document/literal wrapped。其实就是故意在WSDL中定义一个复杂类型complexType节点,该节点的名称与远程调用的方法名相同,该节点把发送的所有参数再封装

文档/文字包装

在我说明文档/文字包装的样式的含义之前,让我给您展示 清单 8和 清单9中的 WSDL 和 SOAP 消息。

Listing 8. Document/literal wrapped WSDL for myMethod
<types>    <schema>        <element name="myMethod">            <complexType>                <sequence>                    <element name="x" type="xsd:int"/>                    <element name="y" type="xsd:float"/>                </sequence>            </complexType>        </element>        <element name="myMethodResponse">            <complexType/>        </element>    </schema></types><message name="myMethodRequest">    <part name="parameters" element="myMethod"/></message><message name="empty">    <part name="parameters" element="myMethodResponse"/></message><portType name="PT">    <operation name="myMethod">        <input message="myMethodRequest"/>        <output message="empty"/>    </operation></portType><binding .../>  <!-- I won't bother with the details, just assume it's document/literal. -->

The WSDL schema now has a wrapper around the parameters (see Listing 9).

Listing 9. Document/literal wrapped SOAP message for myMethod
<soap:envelope>    <soap:body>        <myMethod>            <x>5</x>            <y>5.0</y>        </myMethod>    </soap:body></soap:envelope>

注意到此 SOAP 消息看起来非常类似于 RPC/文字的 SOAP 消息。您可能会说,它看起来与 RPC/文字的 SOAP 消息是完全一样的,不过,这两种消息之间存在着微妙的区别。在 RPC/文字的 SOAP 消息中, <soap:body> 的 <myMethod> 子句是操作的名称。在文档/文字包装的 SOAP 消息中, <myMethod> 子句是单个输入消息的组成部分引用的元素的名称。因此,包装的样式具有这样的一个特征,输入元素的名称与操作的名称是相同的。此样式是把操作名放入 SOAP 消息的一种巧妙方式。

文档/文字包装的样式的特征有:

输入消息只有一个组成部分。

该部分就是一个元素。

该元素有与操作相同的名称。

该元素的复杂类型没有属性。

下面是这种方法的优点和缺点:

优点

没有编码信息,出现在 soap:body 中的每项内容都是由 Schema 定义的,所以您现在可以很容易地检验此消息的有效性,方法名又出现在 SOAP 消息中。

缺点

WSDL 甚至更复杂,但是这仍然是一个非常小的缺点,如您所见,文档/文字包装的样式还是有一些缺点,不过与优点比起来,它们都显得无足轻重。


Why not use document/literal wrapped all the time?

So far, this article has given the impression that the document/literal wrapped style is the best approach. Very often that's true. But there are still cases where you'd be better off using another style.

Reasons to use document/literal non-wrapped

If you have overloaded operations, you cannot use the document/literal wrapped style.

Imagine that, along with the method you've been using all along, you have the additional method in Listing 10.

Listing 10. Problem methods for document/literal wrapped
public void myMethod(int x, float y);public void myMethod(int x);

A note about overloaded operations

WSDL 2.0 will not allow overloaded operations. This is unfortunate for languages like the Java language which do allow them. Specs like JAX-RPC will have to define a name mangling scheme to map overloaded methods to WSDL. WSDL 2.0 merely moves the problem from the WSDL-to-SOAP mapping to the WSDL-to-language mapping.

WSDL allows overloaded operations. But when you add the wrapped pattern to WSDL, you require an element to have the same name as the operation, and you cannot have two elements with the same name in XML. So you must use the document/literal, non-wrapped style or one of the RPC styles.

Reasons to use RPC/literal

Since the document/literal, non-wrapped style doesn't provide the operation name, there are cases where you'll need to use one of the RPC styles. For instance, say you have the set of methods in Listing 11.

Listing 11. Problem methods for document/literal non-wrapped
public void myMethod(int x, float y);public void myMethod(int x);public void someOtherMethod(int x, float y);

Now assume that your server receives the document/literal SOAP message that you saw back in Listing 7. Which method should the server dispatch to? All you know for sure is that it's not myMethod(int x) because the message has two parameters and this method requires one. It could be either of the other two methods. With the document/literal style, you have no way to know which one.

Instead of the document/literal message, assume that the server receives an RPC/literal message such as the one in Listing 5. With this message it's fairly easy for a server to decide which method to dispatch to. You know the operation name is myMethod, and you know you have two parameters, so it must be myMethod(int x, float y).

Reasons to use RPC/encoded

The primary reason to prefer the RPC/encoded style is for data graphs. Imagine that you have a binary tree whose nodes are defined in Listing 12.

Listing 12. Binary tree node schema
<complexType name="Node">    <sequence>        <element name="name" type="xsd:string"/>        <element name="left" type="Node" xsd:nillable="true"/>        <element name="right" type="Node" xsd:nillable="true"/>    </sequence></complexType>

With this node definition, you could construct a tree whose root node -- A -- points to node B through both its left and right links (see Figure 1).

Figure 1. Encoded tree.

The standard way to send data graphs is to use the href tag, which is part of the RPC/encoded style (Listing 13).

Listing 13. The RPC/encoded binary tree
<A>    <name>A</name>    <left href="12345"/>    <right href="12345"/></A><B id="12345">    <name>B</name>    <left xsi:nil="true"/>    <right xsi:nil="true"/></B>

Under any literal style, the href attribute is not available, so the graph linkage is lost (see Listing 14 and Figure 2). You still have a root node, A, which points to a node B to the left and another node B to the right. These B nodes are equal, but they are not the same node. Data have been duplicated instead of being referenced twice.

Listing 14. The literal binary tree
<A>    <name>A</name>    <left>        <name>B</name>        <left xsi:nil="true"/>        <right xsi:nil="true"/>    </left>    <right>        <name>B</name>        <left xsi:nil="true"/>        <right xsi:nil="true"/>    </right></A>
Figure 2. Literal tree

There are various ways you can do graphs in literal styles, but there are no standard ways; so anything you might do would probably not interoperate with the service on the other end of the wire.

SOAP response messages

So far I have been discussing request messages. But what about response messages? What do they look like? By now it should be clear to you what the response message looks like for a document/literal message. The contents of the soap:body are fully defined by a schema, so all you have to do is look at the schema to know what the response message looks like. For instance, see Listing 15 for the response for the WSDL inListing 8.

Listing 15. document/literal wrapped response SOAP message for myMethod
<soap:envelope>    <soap:body>        <myMethodResponse/>    </soap:body></soap:envelope>

But what is the child of the soap:body for the RPC style responses? The WSDL 1.1 specification is not clear. But WS-I comes to the rescue. WS-I's Basic Profile dictates that in the RPC/literal response message, the name of the child of soap:body is "... the correspondingwsdl:operation name suffixed with the string 'Response'." Surprise! That's exactly what the conventional wrapped pattern's response element is called. So Listing 15 applies to the RPC/literal message as well as the document/literal wrapped message. (Since RPC/encoded is not WS-I compliant, the WS-I Basic Profile doesn't mention what an RPC/encoded response looks like, but you can assume the same convention applies here that applies everywhere else.) So the contents of response messages are not so mysterious after all.

Summary

There are four binding styles (there are really five, but document/encoded is meaningless). While each style has its place, under most situations the best style is document/literal wrapped.



0 0
原创粉丝点击