我有一个非常简单的方法,我在WS API中使用JAX-WS注释:
@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,它在没有新参数的情况下工作。
答案 0 :(得分:15)
@WebParam将消息部分映射到参数,而部分不能是可选的。见Optional Message Parts in WSDL。因此,简短的回答是,正是你所要求的无法完成。但是,如果您可以重构此方法,则可以使用下面描述的方法之一。
通常,参数的可选性通过模式minOccurs=0
设置。此外,您可以在架构中定义一个Request参数,而不是使用多个参数,您可以将其定义为WebMethod
的参数。可选项现在封装在参数中,并且对于带或不带可选参数的调用,都会调用相同的方法。
我更喜欢先定义合约,而不是依赖自动生成的文件。一旦你弄清楚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>
在您的WSDL文件中,您可以定义类似的消息:
<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>
此处的WSDL协定定义使用样式:document/literal
,并且在模式的帮助下,实际的SOAP消息将是document/literal wrapped
,这符合WS-I标准。
因此,您的方法将更改为公开MyResponse sendSinge2(MyRequest request)
,其中request
现已封装username
,passowrd
和newParam
。如果newParam
未与SOAP请求一起发送,它只会返回null
,因此在您使用它之前最好先检查一下。
如果您坚持使用代码优先方法,则需要先将MyRequest
类定义为请求参数,而不是那些2或3个值。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "MyRequest", namespace="http://your.namespace.com")
public class MyRequest implements Serializable
{
@XmlElement(name = "username", required = true)
protected String username;
@XmlElement(name = "password", required = true)
protected String password;
@XmlElement(name = "newParam", required = false)
protected String newParam;
...
}
如果你还没有完成MyResult
,也应该这样做。 web方法现在可能看起来像这样:
@WebMethod(operationName = "sendSingle2")
@WebResult(name = "sendSingle2Response", targetNamespace = "http://your.namespace.com")
public MyResult sendSingle2(@WebParam(name = "sendSingle2Request") MyRequest request)
{
...
}
同样,request
封装了3个参数,你应该检查可选参数是否为空。
HTH
答案 1 :(得分:0)
这完全取决于您使用这些参数的实现类。 在端点接口处,只需将此参数添加为webparam。
确保在您的实现类中如果您在任何地方使用此参数,请添加替代代码(Else部分)以执行您的操作或执行而不使用此参数。
我认为除非您验证它们或在您的实现类中按照建议使用它们,否则所有参数都会被视为可选参数。