如何管理API版本控制的逻辑?

时间:2019-10-11 06:01:26

标签: rest api versioning

关于后端实现的逻辑,我想确定API的URI版本化的最佳做法。

假设我们有一个具有以下API的Java应用程序:

http://.../api/v1/user
Request:    
    {
      "first name": "John",
      "last name": "Doe"
    }

过一会儿,我们需要向用户API再添加2个必填字段:

http://.../api/v2/user
Request:    
    {
      "first name": "John",
      "last name": "Doe",
      "age": 20,
      "address": "Some address"
    }

我们为每个版本使用单独的DTO,其中一个具有2个字段,另一个具有4个字段。

对于应用程序,我们只有一个实体,但是我的问题是,作为最佳实践,我们应该如何处理逻辑?可以只在一项服务中处理吗?

如果这两个新字段“年龄”和“地址”不是必填字段,则不会被认为是重大更改,但是既然如此,我认为有几种选择:

  • 对于所有用户API版本,在业务层中仅使用一个管理器/服务(但是代码的复杂性在于,只有一个管理器会随着时间的推移而增长,并且难以维护)
  • 所有用户API版本仅使用一个管理器,并且还使用一个类作为翻译器,因此我可以使新API兼容较旧的API版本
  • 业务层中针对每个用户API版本的新经理/服务

如果我仅对所有用户API版本使用一个管理器,并在其中进行一些约束/验证,则V2可以运行,但V1会引发异常,因为这些字段不存在。

我知道版本控制是一个大话题,但是直到现在我都无法在网络上找到具体答案。 我的直觉说,为所有用户API版本使用一个管理器将导致与干净代码无关的方法,而且,我认为添加新版本的任何更改都必须尽可能松散地耦合,因为使旧方法过时并及时删除它们会更容易。

2 个答案:

答案 0 :(得分:3)

您相信API的版本控制是一个有争议的问题,这是正确的。 您也在进行重大更改,因此增加API版本是正确的决定(w.r.t. semver)。

理想情况下,您的后端代码将受版本控制(例如GitHub)。在这种情况下,您可以放心地将V1视为存储库中的特定提交。这是已部署并为V1提供流量的代码。然后,您可以根据需要继续对代码进行更改。在某些时候,您将添加一些新的重大更改,并决定将特定的提交标记为V2。然后,您可以将V2V1一起部署。当您决定折旧V1时,您可以停止提供流量。

您将需要某种方法来确保仅V1流量流向V1后端,V2流向V2后端。通常,这是通过使用Reverse Proxy完成的;流行的选择包括NGINXApache。任何足够的反向代理都将允许您基于路径定向请求,这样,如果请求以/api/v1为前缀,则将该请求重定向到Backend1,如果以/api/v2为前缀,则重定向到{{1 }}。

希望该模型有助于保持代码的清洁:存储库中的Backend2分支仅需要处理最新的API。如果您需要对旧版API进行更改,可以相对轻松地完成:分支master提交,进行更改,然后将修改后的分支的V1定义为“新” HEAD

对于这个答案,您应该注意一些关于后端的假设。首先,您的后端可以水平缩放。例如,这意味着,如果您与数据库进行交互,则API的多个版本都可以安全地同时访问数据库。其次,您有足够的资源来部署副本后端。

希望这种解释是有意义的;但如果没有任何疑问,请发送给我!

答案 1 :(得分:1)

如果您能够/可以对现有API进行代码更改,则可以参考此 link 。另外, the post 底部提到的链接可将您定向到相应的GitHub源代码,如果您想在试错后引入代码更改,则可能会有所帮助。

所提到的方法(使用@JsonView )基本上可以防止一个人为相同/多个客户引入单个实体的多个DTO。最终,一个人也可以避免每次您在现有API中引入新字段时,都要引入新版本的API。

spring-rest-jackson-jsonview
jackson-jsonview