Spring学习笔记23

    技术2022-05-12  5

    定义Contract

    开发contract-firstweb service最重要的就是定义contract,我们需要定义发送给服务和从服务接收的消息,不用考虑服务被实现的方式和消息被处理的方式。

    虽然这里主要讨论Spring-WS,但其实这和Spring是无关的。因为定义一个web servicecontract与服务的实现细节是独立的。它只关注于它应该有什么而不是它如何去拥有什么。Web servicecontract-first强调与服务通讯的消息。所以,定义contract首先就要确定这些消息的格式。我们将创建一段样本XML消息来定义servicecontract

    创建样本XML消息

           前面的扑克牌服务以五张扑克牌作为输入,产生一个扑克牌名字作为输出。为服务编写一个样吧输入消息的XML代码如下:

    <EvaluateHandRequest

    xmlns="http://www.springinaction.com/poker/schemas">

        <card>

           <suit>HEARTS</suit>

           <face>TEN</face>

        </card>

        <card>

           <suit>SPARES</suit>

           <face>KING</face>

        </card>

        <card>

           <suit>HEARTS</suit>

           <face>KING</face>

        </card>

        <card>

           <suit>DIAMONDS</suit>

           <face>TEN</face>

        </card>

        <card>

           <suit>CLUBS</suit>

           <face>TEN</face>

        </card>

    </EvaluateHandRequest>

    这段XML很直观,总共有5<card>元素,每一个都有一个<suite><face>。这很好地描述了这个扑克牌服务。所有的<card>元素都封装在<EvaluateHandRequest>元素中——这就是我们要发送给service的消息。

           与输入消息类似,输出消息如下:

    <EvaluateHandResponse

        xmlns="http://www.springinaction.com/poker/schemas">

        <handName>Full House</handName>

    </EvaluateHandResponse>

    EvaluateHandResponse消息只包含了一个handName元素,handName保存了输出信息。这些样本消息就是contract的基础。现在我们已经完成了最困难的部分。

    创建数据contract

           现在我们开始创建服务contract。在此之前,我们先把contract从概念上划分几个概念:

    ·data contract:定义与服务通讯的消息。在本例中,这包括EvaluateHandRequestEvaluateHandResponse消息的schema定义。

    ·operational contract:定义服务执行的操作。值得注意的是,一个SOAP操作并不需要关联于服务API中的一个方法。

           一般地,这两个contract部分都被定义在一个单个的WSDL文件中。WSDL文件通常都包含一个内嵌的XML Schema,该Schema定义了data contract。另外,WSDL文件定义了operational contract,在<wsdl:binding>元素中包含一个或多个<wsdl:operation>元素。

           data contract是被定义在XML Schema(XSD)中的,XSD允许我们准确地定义一个消息。我们不但可以定义消息中的元素,还可以指定消息类型和为消息设置限定条件。

           有很多XSD inference工具可供使用,例如TrangTrangXML作为输入产生一个XSD文件作为输出。Trang是基于Java实现的,所以可以应用于任何JVM上。Trang可以产生RELAX NG(一种schema风格)schema,也可以产生XSD文件。对于Spring-WS来说,我们可以使用Trang来产生XSD,执行下面的命令即可得到xsd文件:

    java –jar trang.jar request.xml response.xml PokerTypes.xsd

    Trang将会产生一个名为PokerTypes.xsd的文件,但XSD并不是完美的。因为Trang可以产生XSD,所以Trang对于XML中的数据类型做了一些假设。大多数情况下这些假设没有问题,但是有时候我们还是需要对产生的XSD进行修改调整。

           例如,Trang假设<suit><face>元素的值应该被定义为noncolonized name(xsNCName)。一个noncolonized name不带有命名空间的前缀。我们实际想要的元素只是一个简单的字符串(xsstring)。所以,我们需要把<suit><face>定义为string类型:

    <xs:element name=”suit” type=”xs:string” />

    <xs:element name=”face” type=”xs:string” />

    我们还知道对于<suit>元素只有4个可能的值,所以我们加上限定条件:

    <xs:element name="suit" type="schemas:Suit" />

    <xs:simpleType name="Suit">

        <xsd:restriction base="xs:string">

           <xsd:enumeration value="SPADES" />

           <xsd:enumeration value="CLUBS" />

           <xsd:enumeration value="HEARTS" />

           <xsd:enumeration value="DIAMONDS" />

        </xsd:restriction>

    </xs:simpleType>

    同样地,<face>元素只有13个合法值,这里就不再一一列出其定义了。另外值得注意地是,Trang错误地假定<EvaluateHandRequest>包含一个未限制的<card>元素(maxOccurs=”unbounded”),但是对于本例来说它包含5张卡片。因此,我们需要调整它的定义为:

    <xs:element name="EvaluateHandRequest">

        <xs:complexType>

          <xs:sequence>

            <xs:element minOccurs="5" maxOccurs="5" ref="schemas:card"/>

          </xs:sequence>

        </xs:complexType>

      </xs:element>

    <EvaluateHandResponse>来说,Trang生成的代码还可以,我们当然也可以为其加上限定值,但这不是必须得。

           现在我们已经有了poker hand服务的data contract,但operational contract呢?我们需要WSDL的帮忙。毕竟,WSDL是定义web service的标准。我们当然可以手工编写WSDL,但是这太容易,没有多大乐趣。

           首先要做的就是创建一个服务的端点(endpoint)contract只定义了服务通讯的消息,没有定义它们是如何被处理的。下面来看在Spring-WS中如何创建消息的endpoint,以及Spring-WS如何处理来自服务客户端的消息。


    最新回复(0)