如果这听起来像一个微不足道的问题,请耐心等待。
这不是一个小问题。微不足道的是您可以在网络上找到的所有“Hello World”网络服务示例和教程,它们从未提供任何关于以后如何管理“真实世界”网络服务的建议。
我们应该这样修改现有的网络服务吗?
嗯...不是真的。我将尝试为您的特定情况提供一般性解释以及可能的解决方案,因此请多多包涵(:D),因为这将是一个很长的帖子。
先合同与最后合同
构建 Web 服务有两种方法:先契约和最后契约。
Contract 首先是指创建一个 WSDL,然后生成实现 WSDL 规定的 Contract 的 Java 代码。契约最后意味着创建您的 Java 代码,然后根据代码生成 WSDL。
两者都有优点和缺点,但两者都重要的是合同。
合同
您的 WSDL 描述了合同。部署 Web 服务后,合同必须保持冻结状态。契约是 Web 服务与其客户端之间通信的基础(甚至不要让我开始使用 web services interoperability)。
网络服务和所有客户端在他们的代码中实现这个契约。
我已对 WSDL 进行了更改...
这并不总是一个好主意。
当网络服务合同发生变化时,合同的用户可能会被破坏。当您更改 WSDL 时,您将重新生成 Web 服务代码以支持新合同。但是客户呢?
如果新的修改违反了合同,您将必须指示所有客户获取新合同并更改其代码以适应更改。你有多少客户使用你的这个网络服务?您对 WSDL 做了哪些更改?
合同重大变更与非重大变更
您可以在不破坏客户端的情况下对合同进行一些更改。例如,您可以添加一个新操作。客户在他们的代码中不知道它,他们不知道的东西不会伤害他们。您还可以在现有消息中添加一些可选参数;因为它们是可选的,这意味着它们可以在通信时被省略,并且客户端代码不知道它,他们不知道的东西不会伤害他们。这些是非破坏性更改。
破坏性更改...好吧...违反合同。这些包括例如更改操作名称、更改消息参数类型或名称、添加强制参数等。客户端代码现在已损坏。客户刚刚发现(现有代码不再有效),他们受到了伤害。您的网络服务此时不再可用。
您对 WSDL 执行了哪些类型的更改?
代码
在最后契约的方法中,WSDL 是基于 Web 服务代码生成的。这样做的缺点是将代码实现与 WSDL 联系起来。如果您对代码进行更改,您可能会触发 WSDL 中的更改,从而触发您与客户达成的合同中的更改。
但是,如果在契约优先的方法中,您对 WSDL 进行了更改,然后重新生成了 Web 服务框架代码,那么您再次更改了契约。你没有做得更好......现在你还有另一个问题。您现在再次生成的 Web 服务现有框架代码会发生什么情况?
从 WSDL 生成代码
当您从 WSDL 生成代码时,您将获得 Web 服务框架。这是样板代码,它只是以合同指定的 SOAP 格式在线获取您的 Web 服务消息。
您通常会生成此代码并将其包含在您的项目中以供“重要的”Web 服务代码使用,即实际提供“服务”的代码。如何使用此代码很重要。您必须考虑稍后再次生成代码而不覆盖现有代码的情况。
通常,代码生成工具可以将您的框架代码拆分为一个接口和该接口的一个实现。 您必须放弃生成的实现并提供您自己的接口实现。您在不同的地方提供您的实现,以便在生成骨架代码时它不会被覆盖。如果接口发生变化,你的实现当然会出现编译问题,因为它与新合约不匹配,但至少你仍然有修改它的代码:D。
不幸的是,大多数项目都不会发生这种情况。人们直接修改生成的实现,当他们再次生成骨架时,他们会丢失所有添加的代码。大多数生成工具在代码中插入警告“这是计算机生成的代码。如果再次生成此代码,所有更改都将丢失......”或类似的东西,但人们会听吗?
您的情况可能的解决方案
好吧,废话不多说……
有没有一种方法可以在不覆盖现有代码的情况下对其进行更改?
手动执行(假设它是非破坏性更改)!
这需要一些时间,但并不难做到。您获取原始 WSDL 并在一个单独的文件夹中为其生成代码:Folder1。获取新的 WSDL 并在另一个单独的文件夹中为其生成代码:Folder2。制作两个目录的差异以查看更改了哪些文件。查看文件内部。
您现在知道如何在现有项目代码中更改您的代码。现在您必须找出最初生成的代码在生成后是否以某种方式进行了修改。将项目文件夹与 Folder1 进行比较。
然后手动修改。
如果这是一个可破坏的更改,您可能想看看是否可以迁移客户端。如果没有,您可能必须在两个端点上公开您的 Web 服务,每个端点都有自己的 WSDL 合同到同一个 Web 服务,并随着时间迁移客户端,如果可能的话。