支持不同 REST API 版本的多个模型版本
Supporting multiple versions of models for different REST API versions
是否有实施 API 版本控制的最佳实践?我对以下几点感兴趣:
- 控制器、服务 - 例如我们是否为 API 的每个版本使用不同的控制器 class?较新的控制器 class 是否继承了较旧的控制器?
- 型号 - 如果 API 版本携带同一型号的不同版本 - 我们如何处理转换?例如。如果 API 的 v1 使用模型的 v1,而 API 的 v2 使用模型的 v2,并且我们希望同时支持两者(为了向后兼容)——我们如何进行转换?
- 我可以在 Java 和 Java 脚本中将现有的 frameworks/libraries 用于这些目的吗?
谢谢!
- 我总是建议每个 API 版本使用不同的控制器 class。它使维护人员保持清洁和清晰。通常可以通过复制和粘贴上一个版本来启动下一个版本。您应该 定义明确的版本控制策略;例如 N-2 版本。通过这样做,您最终会得到 3 个并排的实现,而不是某些人认为您会拥有的爆炸。从控制器中重构不特定于 HTTP API 版本的业务逻辑和其他组件有助于减少代码重复。
- 我强烈认为,控制器应该绝对不继承自另一个控制器,除了具有版本中立功能的基本控制器(但不是 APIs) . HTTP 是 API。 HTTP 有 方法 ,没有动词。将其视为
Http.get()
。使用的是另一种语言,例如 Java、C# 等是与 HTTP 阻抗不匹配的外观。 HTTP 不支持继承,因此尝试在实现中使用继承只会加剧不匹配问题。还有其他实际挑战。例如,您可以 取消继承 一个方法,这会使在继承的控制器中取消 API 的问题变得复杂(并非所有版本都是附加的)。调试也可能令人困惑,因为您必须找到正确的实现来设置断点。将一些想法纳入版本控制策略并将责任分解为其他组件都可以,但根据我的经验,不需要继承。
- 模型转换是一个实现细节。这完全取决于服务器。支持转换是非常有情境的。转换可以是双向的 (
v1<->v2
) 或单向的 (v2->v1
)。 Mapper 是一种相当常见的将一种形式转换为另一种形式的方法。附加属性场景通常只需要为旧 API 版本存储新属性的默认值。归根结底,对于所有情况,这个问题没有单一的答案。
- 应该注意 backward-compatibility 在 HTTP 中是用词不当。真的没有这样的东西。 API 版本是包含模型的合同。模型的新版本可以转换的方便或容易 to/from 旧版本的模型应该被认为只是 - 方便。很容易认为附加更改具有向后能力,但服务器不能保证它与客户端一起使用。在 HTTP 上下文中触及 backwards-capable 的概念将帮助您掉入成功的陷阱。
- 使用 Open API(以前称为 Swagger)可能是将客户端与任何语言集成的最佳选择。有一些工具可以使用该文档将客户端创建为您首选的编程语言。对于服务器端的 Java library/framework 我没有具体的建议,但是有几个选项。
是否有实施 API 版本控制的最佳实践?我对以下几点感兴趣:
- 控制器、服务 - 例如我们是否为 API 的每个版本使用不同的控制器 class?较新的控制器 class 是否继承了较旧的控制器?
- 型号 - 如果 API 版本携带同一型号的不同版本 - 我们如何处理转换?例如。如果 API 的 v1 使用模型的 v1,而 API 的 v2 使用模型的 v2,并且我们希望同时支持两者(为了向后兼容)——我们如何进行转换?
- 我可以在 Java 和 Java 脚本中将现有的 frameworks/libraries 用于这些目的吗?
谢谢!
- 我总是建议每个 API 版本使用不同的控制器 class。它使维护人员保持清洁和清晰。通常可以通过复制和粘贴上一个版本来启动下一个版本。您应该 定义明确的版本控制策略;例如 N-2 版本。通过这样做,您最终会得到 3 个并排的实现,而不是某些人认为您会拥有的爆炸。从控制器中重构不特定于 HTTP API 版本的业务逻辑和其他组件有助于减少代码重复。
- 我强烈认为,控制器应该绝对不继承自另一个控制器,除了具有版本中立功能的基本控制器(但不是 APIs) . HTTP 是 API。 HTTP 有 方法 ,没有动词。将其视为
Http.get()
。使用的是另一种语言,例如 Java、C# 等是与 HTTP 阻抗不匹配的外观。 HTTP 不支持继承,因此尝试在实现中使用继承只会加剧不匹配问题。还有其他实际挑战。例如,您可以 取消继承 一个方法,这会使在继承的控制器中取消 API 的问题变得复杂(并非所有版本都是附加的)。调试也可能令人困惑,因为您必须找到正确的实现来设置断点。将一些想法纳入版本控制策略并将责任分解为其他组件都可以,但根据我的经验,不需要继承。 - 模型转换是一个实现细节。这完全取决于服务器。支持转换是非常有情境的。转换可以是双向的 (
v1<->v2
) 或单向的 (v2->v1
)。 Mapper 是一种相当常见的将一种形式转换为另一种形式的方法。附加属性场景通常只需要为旧 API 版本存储新属性的默认值。归根结底,对于所有情况,这个问题没有单一的答案。 - 应该注意 backward-compatibility 在 HTTP 中是用词不当。真的没有这样的东西。 API 版本是包含模型的合同。模型的新版本可以转换的方便或容易 to/from 旧版本的模型应该被认为只是 - 方便。很容易认为附加更改具有向后能力,但服务器不能保证它与客户端一起使用。在 HTTP 上下文中触及 backwards-capable 的概念将帮助您掉入成功的陷阱。
- 使用 Open API(以前称为 Swagger)可能是将客户端与任何语言集成的最佳选择。有一些工具可以使用该文档将客户端创建为您首选的编程语言。对于服务器端的 Java library/framework 我没有具体的建议,但是有几个选项。