为什么不在 REST API 版本控制中考虑模型?

Ayy*_*ppa 0 versioning node.js express swagger ajv

对类似问题有一个答案,但对于示例来说过于具体,并且不能一般性地回答。

如果模型没有版本控制,任何人都可以告诉如何处理以下情况吗?

PUT /v1/users
username (string)
email (string) (required)
password (string) (required)
Run Code Online (Sandbox Code Playgroud)
POST /v2/users
username (string) (required)
email (string) required
password (string) (required)
Run Code Online (Sandbox Code Playgroud)

假设模型名称为UserModel,在 v1 版本中用户名是可选的,但在 V2 中是必需的。

如果我们使用像 ajv 这样的模式验证器,即使对于 v1 api 请求它也会失败,因为最新的规范/模型提到用户名是必填字段。

每个人都应该有充分的理由说模型不应该进行版本控制,但我可能明显遗漏了一些东西。在这种情况下,对模型进行版本控制更有意义,因为它不会轻易破坏向后兼容性。

cas*_*lin 6

您可能会将代表应用程序领域的模型与代表API 处理的数据的模型混淆。

这些是(或者至少应该是不同的关注点,并且应该彼此解耦。当您在应用程序域模型中添加、删除或重命名字段时,您不希望破坏 API 客户端。

话虽如此,虽然您的服务层在域/持久性模型上运行,但您的 API 控制器应该在一组不同的模型上运行。

例如,随着您的域/持久性模型不断发展以支持新的业务需求,您可能希望创建新版本的 API 模型来支持这些更改。随着新版本的发布,您可能还希望弃用API 的旧版本。当您的客户更新其代码时,您可能会放弃对旧版本的支持。


例子

出于示例目的,假设您正在创建一个用于任务管理的应用程序。以下是在您的域中表示任务的方式:

+----------------------+
|         Task         |
+----------------------+
| - id: Long           |
| - title: String      |
| - completed: Boolean |
+----------------------+
Run Code Online (Sandbox Code Playgroud)

您的应用程序将提供 API,以便客户可以管理他们的任务。

要在 API 中创建任务,客户端需要POST该任务的 JSON 表示形式,并使用title和一个布尔值来指示该任务是否存在completed。他们不应该为 提供值id,因为它将由服务器生成。好东西。

有多种方法可以对 API 进行版本控制,其中包括 URL 和媒体类型版本控制。不过,这是一个很大的话题,我不会在这个答案中介绍每种方法的优缺点。但是,出于示例目的,我将使用媒体类型版本控制:

POST /tasks HTTP/1.1
Host: example.org
Content-Type: application/vnd.foo.v1+json

{
  "title": "Send report to manager",
  "completed": false
}
Run Code Online (Sandbox Code Playgroud)

将应用程序发布到生产环境很久之后,您就会意识到使用布尔值来表示任务的状态并不好。使用具有某些值(例如NOT_STARTEDSTARTED和 )的COMPLETED枚举比布尔值更适合您的业务需求。

这需要更改您的域模型和数据库。您的域名将如下所示:

+----------------------+
|         Task         |
+----------------------+
| - id: Long           |
| - title: String      |
| - status: String     |
+----------------------+
Run Code Online (Sandbox Code Playgroud)

因此,您发布了 API 的新版本。任务表示现在具有 astatus而不是 acompleted属性:

POST /tasks HTTP/1.1
Host: example.org
Content-Type: application/vnd.foo.v2+json

{
  "title": "Send report to manager",
  "status": "NOT_STARTED"
}
Run Code Online (Sandbox Code Playgroud)

那酷多了。但不要忘记您的应用程序已经投入生产,并且您不想破坏使用旧 API 的客户端。

因此,您将弃用端点的旧版本,但您将支持它一段时间,以便您的客户可以更新他们的代码。

将旧任务表示映射到任务域模型时,您需要考虑以下事项:

  • 如果completedtrue,那么任务status将是COMPLETED
  • 如果completedfalse,那么任务status将是NOT_STARTED