12

我正在尝试为访问 WSDL 描述的 web 服务的 Java 应用程序编写一个模块。源 WSDL 是直接从我认为是 ASP.NET Web 服务下载的;服务 URL 以 .asmx 扩​​展名结尾,在浏览器中查看服务 URL 会显示一个链接,该链接可用于下载 WSDL。

我的一个关键要求是能够在不重新编译的情况下切换服务 URL。给我的 URL 显然是一个测试服务器,我知道在生产中我会得到一个生产 URL 来使用。我还希望能够自己创建一个模拟服务器进行测试,并保留将来指定新 URL 的能力,而无需在移动服务时重新编译。事实上,我希望安装我们的应用程序能够在不同的 URL 上实例化 Web 服务的多个实例。

但我的概念似乎与 wsimport 工具为我所做的不匹配。按照 f1sh 在此处的回答,我使用以下命令从下载的 WSDL 生成了 Java 代码:

wsimport -Xnocompile -keep -b binding.xml wsdlFile.wsdl

我发现生成的代码具有对我下载的 wsdlFile.wsdl 的硬编码引用,其中包含服务 URL。我们的应用程序不会以通过在运行时编辑 WSDL 文件来配置的方式运行。我需要在构建时将代码编译到我的应用程序中,并且可以在实例化时设置服务 URL。

我不完全确定为什么 WSDL 甚至需要在运行时进行解析;我的理解是 WSDL 提供了足够的信息来生成可以访问 web 服务的代码,所以我不确定它为生成的代码提供了什么而不是服务 URL,我不确定为什么没有提供服务 URL构造函数或可通过生成的 Web 服务类上的方法进行配置。我肯定错过了什么。

这种情况的一般做法是什么?大多数人是否会为他们将要使用的每个单独的 URL 重新生成代码?代码是在运行时生成的吗?我可以使用另一个 WSDL 工具来构建具有可配置 URL 的客户端代码吗?

4

2 回答 2

10

这个答案已经让我想了几天,但不知何故,写这个问题的行为总是让我专注于寻找答案,还有更多的网络搜索指出了这一点:

http://www.fransvanbuul.net/?p=98

似乎 wsimport 创建了一个类 com.example.WebService,它扩展了 javax.xml.ws.Service。这个 WebService 类有两个构造函数。无参数构造函数使用 file:// URL 进行硬编码,以使用我生成的原始 WSDL。(我想如果我在 wsimport 命令行上提供了 https:// URL,那将是硬编码的 URL。)或者,我可以使用两个参数的构造函数并在实例化时提供 WSDL URL!这种方法还要求我提供一个我还不理解的 javax.xml.namespace.QName 对象作为第二个参数。

使用这个双参数构造函数可能会解决我的问题。

我在 JDK 1.6 中使用的 wsimport 似乎是 JAX-WS 包的一部分。在最近的版本中,JDK 1.6 包含 JAX-WS 2.1,而 JAX-WS 2.2 将解决我在这个问题中提出的困难。

我很乐意接受任何解释这种情况的部分或全部其余部分的答案。我仍然不明白为什么在运行时需要 WSDL。更实际地,如果有人向我展示如何使用双参数构造函数,或者如何使用 JDK 1.6 和 JAX-WS 2.2 生成我的代码,将会对我有所帮助。

于 2010-08-25T16:44:47.403 回答
7

这种方法还要求我提供一个我还不理解的 javax.xml.namespace.QName 对象作为第二个参数。

从您生成的源中复制一个。AQName是一个 XML限定名称- 一个“唯一”标识。

我仍然不明白为什么在运行时需要 WSDL。

我不能肯定地说我知道,但是 WSDL 基本上是一个模式。通过提供它,我猜您为 JAX-WS 提供了一种机制来验证 SOAP 响应。我认为 JAXB 绑定不足以做到这一点。

我总是在生成的服务中使用两个参数的构造函数,通过ClassLoader.getResource方法提供一个 URL,以将 WSDL 嵌入到我的 jar 中。与任何模式一样,为此使用远程或文件系统 URL 是愚蠢的,不是最优的。

请参阅此问题以了解如何在运行时设置端点

HelloService service = new HelloService();
Hello port = service.getHelloPort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(
      BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
      "http://foo:8086/HelloWhatever");
String response = port.sayHello(name);
于 2010-08-25T19:30:38.153 回答