3

我开发了一个 Web 服务,它接受和响应一个通用的消息结构。意思是,这个消息结构是通用的。我们使其通用的方式是使用以下 XML 模式:

<xs:complexType name="HeaderType">
<xs:complexType name="MessageType">
<xs:complexType name="PayloadType">

其中 PayloadType 如下:

<xs:complexType name="PayloadType">
        <xs:annotation>
            <xs:documentation>Payload container</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:choice>

                <xs:element name="CreateExceptionSeverity" type="cmsmsg:ExceptionSeverity" minOccurs="0">
                    <xs:annotation>
                        <xs:documentation>CreateExceptionSeverity is a hello world operation that takes in a app id, id, name, and description where the web service creates a new entry in EXCEPTIONSEVERITY table.</xs:documentation>
                    </xs:annotation>
                </xs:element>
                <xs:element name="OperationSet" type="cmsmsg:OperationSet" minOccurs="0">
                    <xs:annotation>
                        <xs:documentation>Each operation set is a collection of operations that may require operational-integrity and/or sequence control.</xs:documentation>
                    </xs:annotation>
                </xs:element>
                <xs:element name="Compressed" type="xs:string" minOccurs="0">
                    <xs:annotation>
                        <xs:documentation>For compressed and/or binary, uuencoded payloads</xs:documentation>
                    </xs:annotation>
                </xs:element>
                **<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other">**
                            <xs:annotation>
                                <xs:documentation>For XML payloads, usually CIM profiles defined using an XSD in a profile-specific namespace.</xs:documentation>
                            </xs:annotation>
                </xs:any>
            </xs:choice>
            <xs:element name="Format" type="xs:string" minOccurs="0">
                <xs:annotation>
                    <xs:documentation>Hint as to format of payload, e.g. XML, RDF, SVF, BINARY, PDF, ...</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

所以,这条线:

<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other">

使此结构足够灵活,可以在调用 Web 服务和 Web 服务发回响应时发送数据。该 Web 服务部署在 TIBCO 服务器(使用 Tomcat)上,将通过 SOAP/HTTP 方式调用。

此 Web 服务的客户端是 Java Spring Web 应用程序。我的问题是:Java 代码如何处理这个 Any 元素,因为它需要一个具体的 XML 类型,如整数、字符串或复杂类型?这里的任何方向将不胜感激。

4

1 回答 1

3

请不要这样做。我以前使用过这类“通用”Web 服务,它们相当于拥有一个 Java API,其中每个方法都有签名

public Object methodName(Object o);

是的,都是非常通用的,但是它没有传达如何使用它的信息(一个设计良好的界面传达了它应该如何使用,就像茶壶的把手暗示茶壶应该被把手拿起一样)。当有人想要开发一个使用您的服务的应用程序时,他们如何确定要发送什么以及他们将返回什么?如果它在其他文档中,那么您基本上已经创建了自己的定制 Web 服务描述语言,它不会与任何工具(如 Spring 或 Axis-2)集成,并且需要编写大量额外的手动代码。

此外,您将不得不在服务实现中编写额外的代码来验证有效负载的内容。这意味着需要额外的维护工作和更高的缺陷几率。

请为您的 Web 服务操作使用具体的 XML 输入和响应,并去掉任何的。它不仅会让你的代码更简单,让你的消费者的代码更简单,它还会消除你提出的关于如何从 Spring 中使用它的问题。

您必须来这里询问如何使用您创建的 Web 服务这一事实应该在您的脑海中敲响警钟。在创建任何类型的界面时,如果您很难使用它,那么其他任何人都将很难使用它。为了确保我的 Web 服务易于使用,我做的第一件事(在创建 WSDL 或实现之前)是创建一个简单的程序,将服务作为测试的一部分调用(例如,JUnit 或 Cucumber-JVM 等) ,只传入需要的数据(仅此而已),并且仅检查它需要的响应数据(仅此而已)。然后我在 Web 服务实现上工作,直到测试通过。这总是会产生易于使用且易于使用的服务,而不是具有高度复杂模式的大型臃肿服务,

对于要包含在消息中的元数据(即 messageType 和 headerType 信息),请考虑按照消息传递元数据 SOA 模式使用SOAP 标头。它们允许您包含额外的信息,而不会污染您的消息正文。

最后,如果您需要在消息结构上应用某种一致性(因为某些奇怪的原因,SOAP 信封还不够,您需要自己定制的信封放入 SOAP 信封),请考虑使用抽象基类型,这然后,您可以扩展以适应该方法的特定需求。这将允许您应用一致性,而无需您的服务消费者猜测“任何”实际上可能是什么。

边注。我工作过的一个客户有一个通用的消息结构,比如你的。原因之一是他们想要一种一致的方式来报告其 Web 服务响应中的成功或错误。因此,在他们定制的响应信封中,有一个指示成功或失败的元素,一切都很好……

...除了服务的消费者,他们现在需要编写额外的代码,不仅要检查 SOAP 错误,还要检查是否设置了定制错误标志。

...除了我们想在我们的服务前面放置一个负载均衡器,因为它本身不支持我们定制的错误元素。但是它确实支持 SOAP 错误和 http 状态代码:/

更新

一种更简单的表达方式。该操作违反了Liskov 替换原则

如果一个操作接受“Any”,我应该期望我传递给该操作的任何有效 xml 元素都可以工作。但是,只允许某些 XML 元素。了解允许哪些类型的唯一方法是了解操作的详细信息。换句话说,操作不如宣传的灵活。

上面的更新是从https://softwareengineering.stackexchange.com/a/198100/37491的优秀答案修改而来的

于 2013-09-09T03:53:40.773 回答