Java 使用不断变化的targetNamespace与SOAP Web服务通信

Java 使用不断变化的targetNamespace与SOAP Web服务通信,java,web-services,soap,namespaces,jax-ws,Java,Web Services,Soap,Namespaces,Jax Ws,所以有一个SOAP Web服务。WSDL中的targetNamespace根据客户的可配置字符串动态更改。想一想 targetNamespace="http://myservice."+ [CouldBeAnyString] + "domain.com" 我有两个问题: 我的基础研究告诉我这是一个相当奇怪的错误?开发Web服务的实践。想法 如何为这样的Web服务编写客户端?我已经使用jax ws存根进行了测试,当targetNamespace发生变化时,它不兼容。还有其他建议吗?我一直试图理解

所以有一个SOAP Web服务。WSDL中的targetNamespace根据客户的可配置字符串动态更改。想一想

targetNamespace="http://myservice."+ [CouldBeAnyString] + "domain.com"
我有两个问题:

我的基础研究告诉我这是一个相当奇怪的错误?开发Web服务的实践。想法

如何为这样的Web服务编写客户端?我已经使用jax ws存根进行了测试,当targetNamespace发生变化时,它不兼容。还有其他建议吗?我一直试图理解基于wsdl的动态客户端生成。如果有的话,我会选择一条更好的路

更新: 我只是客户。服务是由其他人提供的。
同一客户有多个环境,例如测试、生产环境,其中服务托管在不同的targetNamespaces下

如果即使targetNamespace发生了更改,SOAPUI调用仍然有效,那么您可以使用名为的轻量级HTTP库

使用这个库,您不需要生成客户机,因为您是以字符串的形式发送SOAP信封,就像您通过SOAPUI所做的那样


缺点是使用字符串

理论上,创建这样一个Web服务客户端是可行的。 步骤:

使用JDK的wsimport.exe创建基于WSDL的Java构件请参见:作为参考 出于下面显示的代码的目的,我使用了Microsoft提供的计算器WSDL 通过EclipseJ2EE创建动态Web项目 在步骤2中创建的项目的src文件夹下复制步骤1中创建的Java工件。 创建一个包含主方法的新类。通常情况下,您会有类似于: 现在来看棘手的部分:

如果您使用上述WSDL遵循了该示例,那么现在应该有几个带有硬编码名称空间的注释类,例如,iCalCalculator带有以下注释: @WebResultname=result,targetNamespace=…//其中。。。类似于http://example.org

使用Java反射在运行时修改所有硬编码的值参见下面的示例:关于如何修改注释
上述解决方案应该可以做到这一点。

大多数客户端框架都允许您创建一个调用客户端的接口,即创建一个合同接口。它们还为该接口提供了一个实现,该实现具有特定的注释或扩展SOAP感知类,而该接口没有这些细节

从您发布的内容来看,我假设客户端具有相同的接口,只是实现名称空间不同?如果是,则编写应用程序以使用该接口,然后为每个环境的实现构建一个jar。在测试服务器上部署时,使用测试jar部署,而在生产服务器上使用生产jar部署,即根据环境为同一契约选择不同的实现

即使您使用的框架没有为您创建接口,您也可以自己创建一个接口,并将各种实现隐藏在某种类型的接口后面


你也可以像我建议的那样做,但我不会做得像处理字符串那样远。改为使用。

您没有提供一些重要的上下文。您是服务提供商还是客户?为什么WSDL会发生变化?同一客户端的CouldBeAnyString值是否更改?这是区分呼叫者的方法吗?当然。用附加信息更新了这个问题每个环境的名称空间是一个奇怪的设置,至少对我来说这是我第一次看到这个。只是出于好奇,知道他们为什么选择这样做吗?服务提供商提供了一些解释吗?@mishal153:使用客户机是你的选择吗?如果是这样,请注意生成的类没有注释,因此您可以重构它们以动态方式检索名称空间。
String wsdlLocation = "127.0.0.1:8088";//Normally you should retrieve that value dynamically
Url url = new URL(wsdlLocation + "?wsdl");// ?wsdl is actually needed
String namespaceURI = "http://Example.org";//Normally you should retrieve that value dynamically
String localPart = "CalculatorService";// as specified in WSDL file (see name attribute of service tag)
QName qname = new QName(namespaceURI, localPart);
CalculatorService service = new CalculatorService(url,qname);
ICalculator iCalculator = service.getICalculator();
int response = iCalculator.add(1, 2);
System.out.println(response);