wsimport 生成的客户端如何工作?
Posted
技术标签:
【中文标题】wsimport 生成的客户端如何工作?【英文标题】:How does a wsimport generated client work? 【发布时间】:2012-08-27 19:58:11 【问题描述】:首先,我想让您知道我已经可以连接到 Web 服务服务器。我问这个问题是因为我想更深入地了解 wsimport 生成的客户端是如何工作的。根据我的研究,wsimport 使用 JAXWS。请注意,我不了解 JAXWS。
我使用 wsimport 生成了我的客户端。我使用的 WSDL 来自 Axis2 Web 服务,由 Axis2 自动生成。下面的类是wsimport的结果:
com.datamodel.xsd
下
DataBeanRequest.java
DataBeanResponse.java
ObjectFactory.java
package-info.java
com.service
下
MyWebService.java
MyWebServicePortType.java
MyMethod.java
MyMethodResponse.java
ObjectFactory.java
package-info.java
通过上面的类,我可以看出com.datamodel.xsd
包含Web 服务服务器使用的bean(不包括ObjectFactory
和package-info
)。同时MyMethod
和MyMethodResponse
也是用于设置Web服务方法/操作的请求和响应参数的bean。
以下是我的问题:(如果您不知道我的某些问题的答案,您实际上不必回答所有问题。:) 请随时分享您认为我可能找到的任何信息有用。)
我说得对吗
我的上述假设是否正确? 其他类的作用是什么? 我检查了MyWebService
,它包含一个注释,它引用了我用来生成客户端的WSDL 的绝对位置。在客户端指定wsdllocation
有什么相关性?客户如何使用这些信息?
我注意到 Web 服务的实际 URL 没有在任何生成的类中声明。客户端如何知道它需要连接到哪里?
是否对 WSDL 文件进行了注释,以便客户端可以在连接时读取 WSDL 文件上的 URL?如果是这样,是否意味着必须建立新连接时始终读取 WSDL 文件?
wsimport
命令有wsdllocation
属性,其中wsdllocation
的值可以指定。)【问题讨论】:
【参考方案1】:在我回答问题之前,先澄清一下:JAX-WS 是用于在 Java 中实现 Web 服务的规范。它描述了如何将 WSDL 工件映射到 Java 类以及如何使用注释来应用这种映射。你可以download the specification here。工具 wsimport 是本规范参考实现的一部分,参考实现是 Java 类库的一部分。有几种替代实现,例如 Axis2、CXF 或 Metro,它们通过支持其他标准(例如 WS-ReliableMessaging 或 WS-Security)来增强基本 JAX-WS 支持。
现在回答你的问题:
我的上述假设是否正确?
是的,你是。
其他类的作用是什么?
package-info
用于将 Web 服务中使用的 XML 命名空间映射到实现类所在的包。命名空间通常看起来与 Java 包名称不同(通常是 URL),这使得映射成为必要。
ObjectFactory
允许您创建服务发送和接收的任何消息。如果你想在你的存根类前面挂上代码,提供修改过的消息或类似的东西,你需要这个。
我看不到你的类的内容,但如果我理解正确的话,MyWebServicePortType
是一个类似于你的 WSDL 中的portType
的接口。也就是说,它将 WSDL 中的操作及其签名映射到 Java 方法。如果您想提供服务(您不提供服务,您正在询问客户端),则需要实现此接口。在实现客户端时,您只需使用它。
最后,MyWebService
类包含您想要调用 Web 服务所需的客户端存根。
我检查了 MyWebService,它包含一个注解 我用来生成客户端的 WSDL 的绝对位置。什么 在客户端指定 wsdllocation 是否相关?如何 客户是否使用该信息?
您生成的接口包含服务的portType
的签名,但它没有说明如何与服务通信。这是 WSDL 中绑定的一部分。最基本的设置是使用 SOAP over HTTP 的消息的文档/文字样式。其他配置(例如 JMS 上的 SOAP)也是可能的,您的客户端需要知道要使用什么协议。因此它需要绑定 WSDL。此外,正如您稍后所述,您的 Java 文件中没有端点地址。这个地址也是从 WSDL 中读取的。
我注意到 Web 服务的实际 URL 没有在 生成的任何类。客户如何知道它需要什么 连接到?
它从 WSDL 中的service
的port
中读取address
。它位于 WSDL 的末尾。
是否对 WSDL 文件进行了注释,以便客户端可以读取 连接时的 WSDL 文件?
不,port
是具体 Web 服务端点的典型元素。这里没有什么特别需要的。
如果是这样,那是否意味着当一个新的 WSDL 文件总是被读取? 必须建立连接?
嗯,客户端可能有缓存(我不知道这个参考实现的细节)。从概念的角度来看:是的。
如果我需要连接到 HTTPS,该怎么办。如何设置服务器 证书
这可能很棘手,我不能给你一个开箱即用的答案。我建议阅读有关此主题的问题,such as this one。
当我使用 wsimport 和 当我使用 Axis2 或 Apache CXF 生成它时
是的,有。 wsimport 更好,不要使用 wsdl2java。 Here is a description, why.
【讨论】:
再次感谢! :D 你也是回答我上一个问题的人。我只想澄清这一点:JAXWS 是 Web 服务的 Java 规范。 Java、CXF、Axis2 等是实现 JAXWS 规范的 API/框架的示例。我说得对吗?另外,在生成客户端存根时,您可以对 wsimport 与 CXF 说些什么?您给我的链接仅将 wsimport 与 Axis2 进行比较。 Axis2 的附加功能,CXF 与 Java 的普通 JAXWS 相比真的有用吗(考虑到您将使用它来开发 Web 服务客户端,而不是服务器。)? 是的,我也喜欢这个自动取款机 :) 是的,你说得对。关于 wsdl2java 与 wsimport: 不幸的是,我不能给你确凿的事实,但只有口耳相传的建议。 CXF 和 Axis2 对它们的代码生成工具的命名是一样的,但它们是不同的。我在axis2 wsdl2java方面有过不好的经历,但在cxf wsdl2java方面没有经验。到目前为止,我对 wsimport 没有负面经验。我什至用它来生成也使用 CXF 的客户端存根。根据我的经验和阅读,CXF 是一个很好的 WS-stack。 关于附加功能:您需要docs.oasis-open.org/ws-rx/wsrm/200702 或oasis-open.org/committees/tc_home.php?wg_abbrev=wss 之类的东西吗?换句话说:您调用的服务是否使用策略? (在 WSDL 中查找策略元素)。如果不是,那么参考实现很可能就足够了。其中一个堆栈可能具有性能优势,但几乎没有任何数据。 谢谢!我也没有使用CXF的经验。另一方面,我对Axis2只有一点基础知识,对JAX-WS知之甚少。关于附加功能,老实说,我不确定我需要什么。我只想问它是否可以使某些事情变得更容易。我可能需要研究什么是政策。我以前读过 WS-POLICY,但我不确定它的作用。 WS-Policy 允许您为服务配置非功能属性(消息加密,...)。这个想法是服务定义了一个策略,客户端和服务的 WS 堆栈(axis2,cxf,...)使其工作,而无需在客户端或服务端进行额外的编码。由于您已经可以连接到该服务,我假设它没有定义策略,您可以安全地使用参考实现。【参考方案2】:您问:我注意到 Web 服务的实际 URL 没有在任何生成的类中声明。客户端如何知道它需要连接到哪里?
如果 WSDL 是使用浏览器下载并作为输入传递给 wsimport,则本地 wsdl 文件位置将嵌入到生成的代码中。这就是您在生成的代码中看不到实际服务位置的原因。这也意味着如果您删除了 wsdl 文件的本地副本,生成的代码将无法工作(当使用 main 方法调用时)。
如果 wsdl 的 URL 作为输入传递给 wsimport,则该 URL 嵌入在生成的代码中,该代码进一步用于获取实际的服务位置。这个想法是 WSDL 位置是固定的。它们应该位于 UDDI 中或作为本地文件。这允许实际服务移动,如果它们移动,您只需单独修改 wsdl 文件的本地副本或更新 UDDI 中的 wsdl。 [大多数情况下这不会发生,因为服务位置从来都不是 IP,而是 DNS 名称]
这就是为什么在运行 Web 服务的同一台服务器上发布 wsdl 绝不是一个好主意
【讨论】:
以上是关于wsimport 生成的客户端如何工作?的主要内容,如果未能解决你的问题,请参考以下文章