我的应用程序分为两层,后端层公开了一堆Web服务,表示层使用这些层来获取业务数据。
为了使我的构造尽可能自动化,我将所有生成的WSDL和相关的XSD文件打包成ZIP依赖项(使用Maven汇编程序插件),在安装阶段上传到我的nexus。
然后在UI POM上我将这个ZIP文件(使用maven依赖插件)解压缩到本地目录(src/main/resources/wsdl
),然后使用CXF-CODEGEN插件生成客户端。
问题是 - 许多这些服务共享通用模型实体,例如,许多方法使用Catalogue
类,这是我用于由Id和文本值组成的对象的实体。
使用CXF生成的代码,我最终为每个Web服务提供了一个不同的Catalogue
类(具有不同的包名称),因此在我的代码中失去了OO polimorphism功能,因为它们在实践中都是不同的类。 / p>
我听说你可以通过某种方式将XSD类首先编译成称为“剧集”的东西,然后将这些剧集文件提供给CXF,以告诉它利用它们而不是生成类来避免这个问题。
我试图添加一个额外的编译步骤,我在其中运行maven-jaxb2-plugin来从XSD生成类,但是我得到了一个
org.xml.sax.SAXParseException; (...) 'catalogueDTO' is already defined
异常,因为此类在XSD文件中重复。
有人能指出我正确的方向吗?
答案 0 :(得分:2)
如果您的Web服务中有一些将在服务和操作中使用的基类,最好在单个XSD中声明这些类,然后在整个项目中包含和使用此XSD。
以下示例将向您展示如何操作。我将此示例基于所提供的信息,因此它可能不完全符合您的需要,但会向您展示概念。
首先,我们创建一个Catalog.xsd文件,并使用以下代码在此文件中声明我们的目录对象:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns="http://www.yourcompany.com/Services_V1/CommonType"
elementFormDefault="qualified"
targetNamespace="http://www.yourcompany.com/Services_V1/CommonType"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="CatalogueID_Type">
<xs:annotation>
<xs:documentation>The Catalogue ID is an integer value that is used to uniquely identify the catalog item on the database.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:int" />
</xs:simpleType>
<xs:simpleType name="CatalogueValue_Type">
<xs:annotation>
<xs:documentation>The catalog is a string value that will contain the information describing the catalog key.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string" />
</xs:simpleType>
<xs:complexType name="Catalogue_Type">
<xs:sequence>
<xs:element ref="CatalogID"
minOccurs="1"
maxOccurs="1" />
<xs:element ref="CatalogueValue"
minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:element name="CatalogID"
type="CatalogueID_Type" />
<xs:element name="CatalogueValue"
type="CatalogueValue_Type" />
<xs:element name="Catalogue"
type="Catalogue_Type" />
或者如果你喜欢视觉表现:
需要注意的是,目录类/对象的名称空间为http://www.yourcompany.com/Services_V1/CommonType
,我们将在WSDL中再次使用此命名空间。现在,这两个服务将由BathroomCatalogue Service和KicthenCatalogue Service使用。为简单起见,我在服务中只有一个名为GetCatalogueItem的操作。对于这些服务中的每一个,我将包含catalog.xsd
文件并重用此目录对象。
以下是浴室服务的WSDL:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="BathroomCatalogueSRV"
targetNamespace="http://www.yourcompany.com/Services_V1/BathroomCatalogueService"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://www.yourcompany.com/Services_V1/BathroomCatalogueService"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:catalogue="http://www.yourcompany.com/Services_V1/CommonType">
<wsdl:types>
<xs:schema elementFormDefault="qualified"
targetNamespace="http://example.com/">
<xs:import schemaLocation="Catalog.xsd"
namespace="http://www.yourcompany.com/Services_V1/CommonType" />
</xs:schema>
</wsdl:types>
<wsdl:message name="GetCatalogueItemReq">
<wsdl:part name="GetCatalogueItemReq"
element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:message name="GetCatalogueItemRs">
<wsdl:part name="GetCatalogueItemRs"
element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:portType name="BathroomCataloguePortType">
<wsdl:operation name="GetCatalogueItem">
<wsdl:input message="tns:GetCatalogueItemReq" />
<wsdl:output message="tns:GetCatalogueItemRs" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BathroomCatalogueBinding"
type="tns:BathroomCataloguePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<wsdl:operation name="GetCatalogueItem">
<wsdl:input />
<wsdl:output />
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BathroomCatalogueService">
<wsdl:port name="BathroomCataloguePort"
binding="tns:BathroomCatalogueBinding">
<soap:address location="http://www.yourcompany.com/Services_V1/BathroomCatalogueService" />
</wsdl:port>
</wsdl:service>
或者如果你想要一个视觉表现:
Kitchen WSDL看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="KitchenCatalogueSRV"
targetNamespace="http://www.yourcompany.com/Services_V1/KitchenCatalogueService"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://www.yourcompany.com/Services_V1/KitchenCatalogueService"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:catalogue="http://www.yourcompany.com/Services_V1/CommonType">
<wsdl:types>
<xs:schema elementFormDefault="qualified"
targetNamespace="http://example.com/">
<xs:import schemaLocation="Catalog.xsd"
namespace="http://www.yourcompany.com/Services_V1/CommonType" />
</xs:schema>
</wsdl:types>
<wsdl:message name="GetCatalogueItemReq">
<wsdl:part name="GetCatalogueItemReq"
element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:message name="GetCatalogueItemRs">
<wsdl:part name="GetCatalogueItemRs"
element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:portType name="KitchenCataloguePortType">
<wsdl:operation name="GetCatalogueItem">
<wsdl:input message="tns:GetCatalogueItemReq" />
<wsdl:output message="tns:GetCatalogueItemRs" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="KitchenCatalogueBinding"
type="tns:KitchenCataloguePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<wsdl:operation name="GetCatalogueItem">
<wsdl:input />
<wsdl:output />
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="KitchenCatalogueService">
<wsdl:port name="KitchenCataloguePort"
binding="tns:KitchenCatalogueBinding">
<soap:address location="http://www.yourcompany.com/Services_V1/KitchenCatalogueService" />
</wsdl:port>
</wsdl:service>
再一次在视觉上:
在这两个WSDL文件中,我都包含了catalog.xsd文件。您可以在以下代码行中看到这一点:
<xs:import schemaLocation="Catalog.xsd"
namespace="http://www.yourcompany.com/Services_V1/CommonType" />
现在,当我将这些WSDL和XSD与cxf一起使用时,两个服务只会使用一个目录对象/类。我很快做了一个shell项目,并生成了以下结构:
请注意,CatalogueType I声明现在位于一个包中,其中包含我声明的命名空间。
在查看服务类时,浴室和厨房服务都将使用这一类。在厨房服务类中,它使用com.yourcompany.services_v1.commontype.CatalogueType
。
@WebService(targetNamespace = "http://www.yourcompany.com/Services_V1/KitchenCatalogueService", name = "KitchenCataloguePortType")
@XmlSeeAlso({com.yourcompany.services_v1.commontype.ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface KitchenCataloguePortType {
@WebResult(name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType", partName = "GetCatalogueItemRs")
@WebMethod(operationName = "GetCatalogueItem")
public com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItem(
@WebParam(partName = "GetCatalogueItemReq", name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType")
com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItemReq
);
}
在厨房服务类中,它使用com.yourcompany.services_v1.commontype.CatalogueType
。
@WebService(targetNamespace = "http://www.yourcompany.com/Services_V1/BathroomCatalogueService", name = "BathroomCataloguePortType")
@XmlSeeAlso({com.yourcompany.services_v1.commontype.ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface BathroomCataloguePortType {
@WebResult(name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType", partName = "GetCatalogueItemRs")
@WebMethod(operationName = "GetCatalogueItem")
public com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItem(
@WebParam(partName = "GetCatalogueItemReq", name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType")
com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItemReq
);
}
提醒您,您必须永远不要编辑这些类,因为它们是由CXF派生和生成的,您的更改将会丢失。因此,通过执行WSDL第一种方法,您必须确保正确构建XSD文件和WSDL。
如果这是有道理的,请告诉我。