Java 中 2 个 SOAP 网络服务之间的公共 request/response 对象

Common request/response objects between 2 SOAP webservices in Java

在我的项目中,我们必须首先调用 2 个具有相同 Request/Response 对象的合同 SOAP Web 服务。

由于 Web 服务首先是合同,我使用 CXF wsdl2java 创建了 类,现在我在 2 个包中有 2 套相同的 类。有没有办法可以将那些 类 重构为一组 类.

为了描述更多,我有 2 个包,每个包含以下 类,具有完全相同的属性和代码:

@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"loginRequest", "request"})
@XmlRootElement(name = "requestHolder")
public final class RequestHolder {
    @XmlElement(required = true)
    private LoginRequest loginRequest;
    @XmlElement(required = true)
    private RequestData request;
}

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "LoginRequest", propOrder = {"username", "password"})
public final class LoginRequest {
    @NotBlank
    @XmlElement(required = true)
    private String username;
    @NotBlank
    @ToString.Exclude
    @XmlElement(required = true)
    private String password;
}

@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "requestData")
public final class RequestData {
    @XmlElement(required = true)
    private String statementId;
    @XmlElement(required = true)
    private String tracker;
    @XmlElement(required = true)
    private int depositCount;
    @XmlElement(required = true)
    private long depositAmount;
    @XmlElement(required = true)
    private int withdrawalCount;
    @XmlElement(required = true)
    private long withdrawalAmount;
    @XmlElement(required = true)
    private int unknownCount;
    @XmlElement(required = true)
    private long unknownAmount;
    @XmlElement(required = true)
    private int duplicateCount;
    @XmlElement(required = true)
    private long duplicateAmount;
    @XmlElement(required = true)
    private int okCount;
    @XmlElement(required = true)
    private long okAmount;
    @XmlElement(required = true)
    private String processCode;
    @XmlElement(required = true)
    private String processMessage;

}

@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"exception", "result"})
@XmlRootElement(name = "responseHolder")
public final class ResponseHolder {
    @XmlElement(name = "Exception", required = true)
    private ExceptionHolder exception;
    @XmlElement(name = "Result")
    private Result result;
}

@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "exceptionHolder", propOrder = {"code", "message"})
public final class ExceptionHolder {
    @XmlElement(name = "Code", required = true)
    private String code;
    @XmlElement(name = "Message", required = true)
    private String message;
}

@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "result")
public final class Result {
    @XmlElement(name = "Receipt", required = true, nillable = true)
    private String receipt;
}

然后我有 2 个 WebService 接口,它们也彼此相似(绑定到不同的端点),具有不同的 WebService 方法名称

@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@WebService(targetNamespace = Service1.TARGET_NAMESPACE, name = "Service1")
@XmlSeeAlso(ObjectFactory.class)
public interface Service1 {

    String TARGET_NAMESPACE = "http://www.mycompany.com/service1Namespace";

    @WebMethod
    @WebResult(name = "responseHolder", targetNamespace = TARGET_NAMESPACE, partName = "responseHolder")
    ResponseHolder serviceMethod1(
            @WebParam(partName = "requestHolder", name = "requestHolder", targetNamespace = TARGET_NAMESPACE) RequestHolder requestHolder);
}


@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@WebService(targetNamespace = Service2.TARGET_NAMESPACE, name = "Service2")
@XmlSeeAlso(ObjectFactory.class)
public interface Service2 {

    String TARGET_NAMESPACE = "http://www.anotherCompany.com/service2Namespace";

    @WebMethod
    @WebResult(name = "responseHolder", targetNamespace = TARGET_NAMESPACE, partName = "responseHolder")
    ResponseHolder serviceMethod2(
            @WebParam(partName = "requestHolder", name = "requestHolder", targetNamespace = TARGET_NAMESPACE) RequestHolder requestHolder);
}

如您所见,只有命名空间和服务端点以及方法名称不同。 除了这 2 个服务接口之外,还有 2 个 package-info.java 文件,它们使用不同的命名空间进行注释。

当我尝试将公共 类 移动到另一个包并使用它们时,由于它们与带注释的 package-info.java 文件不在同一个包中,因此它们的名称空间未正确添加到请求中信封,我在服务端点遇到错误。

那么问题来了,我怎样才能使用1套request/response 类,有可能吗?

它有点复杂,但您可以指定(在应用 wsdl2java 时)一个“绑定文件”,它将允许您通过 XJC 自定义生成 Java 类 的方式(例如包名称、类型映射等...)

在您的特定情况下,您应该查看“”:

A .episode file is generated by the XJC (XML Schema to Java) compiler. It is a schema bindings that associates schema types with existing classes. It is useful when you have one XML schema that is imported by other schemas as it prevents the model from being regenerated.

(老但是)有趣的文章:

https://dzone.com/articles/reusing-generated-jaxb-classes