Java SOAP-WS-make@WebParam可选

Java SOAP-WS-make@WebParam可选,java,web-services,soap,jaxb,jax-ws,Java,Web Services,Soap,Jaxb,Jax Ws,我有一个非常简单的方法,通过JAX-WS注释在WS-API中使用: @WebMethod public MyResponse sendSingle2( @WebParam(name="username") String username, @WebParam(name="password") String password, @WebParam(name="newParam") String newParam) { // the code } 现

我有一个非常简单的方法,通过JAX-WS注释在WS-API中使用:

@WebMethod
public MyResponse sendSingle2(
    @WebParam(name="username") String username,
    @WebParam(name="password") String password,
    @WebParam(name="newParam") String newParam) {
        // the code
    }
现在我希望newParam是可选的。我的意思是,我希望该方法不仅在传递的xml中参数为空时仍然有效:

<ws:sendSingle2>
    <username>user</username>
    <password>pass</password>
    <newParam></newParam>
</ws:sendSingle2>

用户
通过
但当它不存在时:

<ws:sendSingle2>
    <username>user</username>
    <password>pass</password>
</ws:sendSingle2>

用户
通过

我需要它不要破坏现有的API,它在没有新参数的情况下工作。

这取决于您使用这些参数的实现类。 在端点接口,只需将此参数添加为webparam

如果在任何地方使用此参数,请确保在实现类中添加替代代码(Else部分)来执行操作或执行,而不使用此参数


我认为所有参数都视为可选的,除非您按照建议验证它们或在实现类中使用它们。

@webgram将消息部分映射到参数,而部分不能是可选的。看见因此,简单的回答是,你所要求的恰恰是无法实现的。但是如果你能重构这个方法,你可以使用下面描述的方法之一

通常通过模式
minOccurs=0
设置参数的可选性。此外,您可以在模式中定义一个请求参数,作为
WebMethod
的参数,而不是使用多个参数。optionality现在封装在参数中,并且对于带有或不带有可选参数的调用调用相同的方法

我更喜欢先定义合同,而不是依赖自动生成的文件。一旦您了解了XSD、SOAP和WSDL是如何结合在一起的,您就很难再使用基于注释/代码优先的定义了,因为您在另一方面更加灵活

代码示例:

<xs:schema
    targetNamespace="http://your.namespace.com"
    xmlns:tns="http://your.namespace.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFromDefault="qualified"
    attributeFromDefault="qualified">

...

<xs:element name="MyRequest" type="tns:MyRequestType" />
<xs:element name="MyResponse" type="tns:MyResponseType" />

<xs:complexType name"MyRequestType">
    <xs:sequence>
        <xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1" />
        <xs:element name="password" type="xs:string" minOccurs="1" maxOccurs="1" />
        <xs:element name="newParam" type="xs:string" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
</xs:complexType>

...

</xs:schema>
如果您还没有完成,
MyResult
也应该执行同样的操作。web方法现在看起来可能类似于:

<wsdl:definitions
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:msg="http://your.namespace.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    targetNamespace="http://your.namespace.com">

    <wsdl:types>
        <xs:schema>
            <!-- either import the externalized schema -->
            <xs:import namespace="http://your.namespace.com"
                       schemaLocation="someDir/yourMessageSchema.xsd" />
        </xs:schema>
        <!-- or define the schema within the WSDL - just copy the schema here -->
        <xs:schema
            targetNamespace="http://your.namespace.com"
            xmlns:tns="http://your.namespace.com"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            elementFromDefault="qualified"
            attributeFromDefault="qualified">
                ...
        </xs:schema>
    </wsdl:types>

    ...

    <wsdl:message name="sendSingle2Request">
        <wsdl:part name="in" element="msg:MyRequest" />
    </wsdl:message>

    <wsdl:message name="sendSingle2Response">
        <wsdl:part name="out" element="msg:MyResponse" />
    </wsdl:message>

    ...

    <wsdl:portType name="YourServiceEndpoint">
        <wsdl:operation name="sendSingle2">
            <wsdl:input message="tns:sendSingle2Request" />
            <wsdl:output message="tns:sendSingle2Response" />
        </wsdl:operation>
        ...
    </wsdl:portType>

    <wsdl:binding name="YourServiceBinding" type="YourServiceEndpoint">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name=""sendSingle2">
            <soap:operation soapAction="http://your.namespace.com/SendSingle2" style="document" />
            <wsdl:input>
                <soap:body parts="in" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body parts="out" use="literal" />
            </wsdl:output>
        </wsdl:operation>
        ...
    </wsdl:binding>

    <wsdl:service name="YourService">
        <wsdl:port name="YourServicePort binding="tns:YourServiceBinding">
            <soap:address location="http://your.server:port/path/to/the/service" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
@WebMethod(operationName = "sendSingle2")
@WebResult(name = "sendSingle2Response", targetNamespace = "http://your.namespace.com")
public MyResult sendSingle2(@WebParam(name = "sendSingle2Request") MyRequest request)
{
   ...
}
同样,
request
封装了3个参数,您首先应该检查可选参数是否为空


嗯,不是那么简单。这个方法甚至没有被输入,因为它在方法调用之前失败了。我不能理解你,我只是解释了概念。我编辑了源代码,并在那里添加了“newParam”。我希望在这两种情况下都调用我的方法(带注释的@WebMethod),并包含两个SOAP片段。现在,只有在SOAP消息(第一个XML片段)中包含“”时才调用它。如果没有包含(第二个XML代码段),甚至不会调用我的方法。正如这个问题的答案()所暗示的那样,恐怕我想要实现的目标是不可能的。请稍等,让我试试这个,虽然上面的答案似乎是合理的,但应该有办法。谢谢。“这就是我想要采取的方式。”Roman Vottner解释得很好。你能推荐一个好地方开始学习web服务中的契约优先开发方法吗?关于WSDL、SOAP和XSD?有书吗?@Octopus通常维基百科条目(,)都是很好的起点。谷歌和其他公司也提供了足够多的关于这个问题的好链接。阅读WSDL规范可能也会有所帮助,但不是强制性的。F.e:还有一些有用的信息too@RomanVottner你能解释一下如何用rpc/literal来实现吗?。我目前正在做一个需要使用rpc的项目。一旦我有了wsdl,如何生成java服务。我已经尝试了所有在互联网上找到的教程,但没有一个有效。我正在使用JBossEAP6.4
@WebMethod(operationName = "sendSingle2")
@WebResult(name = "sendSingle2Response", targetNamespace = "http://your.namespace.com")
public MyResult sendSingle2(@WebParam(name = "sendSingle2Request") MyRequest request)
{
   ...
}