RESTful Web 服务版本控制 - 使用 URI 的基本方法

2025年1月18日 | 阅读 7 分钟

版本控制是 API 中最重要也是最困难的部分,因为它需要向后兼容 API。版本控制帮助我们在识别出变更后更快地迭代。我们应该始终对 Web API 进行版本控制。

设想一个场景,我们有一个正在运行的 Web API。用户正在消费该 API。现在我们想在 Web API 中添加更多功能,但想保持现有功能不变。可能有一些用户仍然想使用旧的 API,而另一些用户想要一个带有新功能或扩展功能的新版本 API。这就是 Web API 版本控制的出现场景。

何时需要版本控制

当我们在 Web API 中进行了破坏性更改时,应该对 API 进行版本升级。破坏性更改包括:

  • 一个或多个调用的响应数据格式发生更改。
  • 响应类型发生更改。
  • 移除 API 的任何部分。

破坏性更改应始终导致 API 的主版本号或内容响应类型发生更改。

非破坏性更改(添加新端点或新响应参数)不需要更改主版本号。但是,跟踪 API 的次版本可能很有帮助。

如何进行版本控制

最常用的方法分为三类:

  • URI 版本控制
  • 使用自定义请求头进行版本控制
  • 使用 Accept 头进行版本控制

URI 版本控制

URI 版本控制是最直接的方法。它在 URL 中以查询字符串的形式指定。它违反了 URI 应指向唯一资源的原则。当版本更新时,你也很难保证客户端集成不会中断。Twitter 使用 URI 版本控制。

示例

http://api.demo.com/v1
http://apiv1.demo.com

版本不必是数字,也不必使用 v[x] 语法。替代方案包括日期、项目名称、季节或其他有意义的标识符,这些标识符在版本更改时也会相应更改。

使用自定义请求头进行版本控制

自定义头允许我们保留 URL。它与现有 Accept 头实现的 Content Negotiation 行为相同。版本信息在请求头中指定,而无需更改 URL。Microsoft 使用请求头版本控制。用户无法在普通浏览器(Chrome)中访问请求头版本控制。我们需要一个特殊的插件才能在浏览器中访问它们。

示例

Accept-version: v1
Accept-version: v2

使用 Accept 头进行版本控制

Accept 头定义了媒体类型和字符编码。我们还可以通过 accept 头传递 Web API 的版本信息,而无需更改 URL。它也被称为媒体类型版本控制、Content Negotiation 或 Accept 头。Github 使用 Accept 头版本控制。用户无法在普通浏览器(Chrome)中访问 Accept 头版本控制。我们需要一个特殊的插件才能在浏览器中访问它们。

示例

Accept: application/vnd.demo.v1+json Accept:application/vnd.demo+json;version=1.0

让我们看看如何在项目中实现版本控制。

URI 版本控制

步骤 1:com.javatpoint.server.main.versioning 包中创建一个名为 PersonV1.java 的类。PersonV1 表示 API 的第一个版本。API 的初始版本有一个 name 变量。

PersonV1.java

步骤 2:随着时间的推移,我们认识到需要分别拥有姓和名。所以我们创建了一个名为 Person2.java 的类。它表示 API 的第二个版本。

PersonV2.java

步骤 3:创建一个名为 Name.java 的类,该类有两个变量 firstName 和 lastName。

Name.java

旧版本仍然返回全名,而第二个版本分别返回名字和姓氏。现在我们需要为同一服务创建两个不同的版本。

让我们看看如何为同一服务创建两个不同的版本,以及这些服务有哪些不同的版本。

步骤 4:Name.java 文件中,生成 Getter 和 Setter,生成带字段的构造函数。创建 Name 类的无参构造函数。

Name.java

步骤 5:打开 PersonV1.java 类。生成 Getter 和 Setter,生成带字段的构造函数。创建 PersonV1.java 类的无参构造函数。

PersonV1.java

步骤 6:打开 PersonV2.java。生成 Getter 和 Setter,生成带字段的构造函数。创建 PersonV2.java 类的无参构造函数。

PersonV2.java

现在我们需要创建一个服务。

步骤 7:创建一个名为 PersonVersioningController.java 的类。为不同的版本创建两个方法,并将它们映射到不同的 URI。

PersonVersioningController.java

步骤 8:打开 Postman 并使用 URI https://:8080/v1/person 发送 GET 请求。它返回全名,如下图所示。

Versioning RESTful Web Services-Basic Approach With URIs

更改 URI https://:8080/v2/person 以获取第二个版本。它分别返回名字和姓氏,如下图所示。

Versioning RESTful Web Services-Basic Approach With URIs

使用请求参数进行版本控制

实现版本控制的另一种方法是使用请求参数。Amazon 使用请求参数版本控制。打开 PersonVersioningController.java 并进行以下更改:

  • 将第一个方法的 URI 从 /v1/person 更改为 /person/param。
  • 将方法的名称从 personV1 更改为 paramV1。
  • 类似地,将第二个方法的 URI 从 /v2/person 更改为 /person/param。

两个方法都有相同的 get 映射,所以我们将使用 value 和 params 属性来区分它们。value 属性包含我们想要使用的 URI,params 属性包含区分版本的参数。

PersonVersoningController.java

现在,转到 Postman 并使用 URI https://:8080/person/param?version=1 发送 GET 请求。它返回全名,如下图所示。

Versioning RESTful Web Services-Basic Approach With URIs

再次,生成一个使用 URI https://:8080/person/param?version=2 的 GET 请求以访问第二个版本。它分别返回名字和姓氏,如下图所示。

Versioning RESTful Web Services-Basic Approach With URIs

使用请求头进行版本控制

还有一种使用请求头进行版本控制的方法。它类似于 Content Negotiation。在这种方法中,我们根据请求头区分服务。

PersonVersioningController.java 中,执行以下操作:

  • 复制这两个方法并将它们粘贴到同一个文件中。
  • 将方法名 paramV1 更改为 headerV1,将 paramV2 更改为 headerV2。
  • 将 URI /person/param 替换为 /person/header,将 params 替换为 headers。

打开 Postman

  • 选择 Headers 选项卡,设置 Key:X-API-VERSION,Value:1。
  • 输入 URI https://:8080/person/header 并发送 GET 请求。

它返回全名。

Versioning RESTful Web Services-Basic Approach With URIs

让我们发送版本 2 的 GET 请求。为此,我们需要在 Headers 选项卡下将 Value 从 1 更改为 2。它分别返回名字和姓氏。

Versioning RESTful Web Services-Basic Approach With URIs

使用 Accept 头进行版本控制

另一种用于版本控制的方法是 Accept Header。它也被称为 Content Negotiation 或 Accept Versioning。在这种方法中,我们使用一个名为 produce 的属性。它表示我们为特定服务生成什么样的输出。

PersonVersioningController.java 文件中,执行以下操作:

  • 复制这两个方法并将它们粘贴到同一个文件中。
  • 将方法名 headerV1 更改为 producesV1,将 headerV2 更改为 ProducesV2。
  • 将 URI /person/header 替换为 /person/produces,将 header 替换为 produces。

打开 Postman

  • 选择 Headers 选项卡,设置 Key:Accept,Value:application/vnd.company.app-v1+json。
  • 取消选中 X-API-VERSION 键。
  • 输入 URI https://:8080/person/produces 并发送 GET 请求。

它返回全名。

Versioning RESTful Web Services-Basic Approach With URIs

让我们发送版本 2 的 GET 请求。为此,我们需要将 Value 从 Value: application/vnd.company.app-v1+json 更改为 Value: application/vnd.company.app-v2+json

它分别返回名字和姓氏。

Versioning RESTful Web Services-Basic Approach With URIs