您将學到
- 為什麼我們需要對RESTful API 進行版本控制?
- 可用的版本控制有哪些?
- 如何實作基于 Restful 的版本控制?
為什麼我們需要對RESTful API進行版本化
最好的版本控制方法是不進行版本控制。隻要不需要版本控制,就不要版本控制。
建構向後相容的服務,以便盡可能避免版本控制!
然而,在許多情況下我們都需要進行版本控制,然我們看看下面具體的例子:
最初,你有個這個版本的Student服務,傳回資料如下:
{
"name": "Bob Charlie"
}
後來,您希望将學生的名字拆分,是以建立了這個版本的服務。
{
"name": {
"firstName": "Bob",
"lastName": "Charlie"
}
}
您可以從同一個服務支援這兩個請求,但是随着每個版本的需求多樣化,它會變得越來越複雜。
在這種情況下,版本控制就成必不可少,強制性的了。
接下來讓我們建立一個簡單的SpringBoot的maven項目,并了解對 RESTful 服務進行版本控制的4種不同方法。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
幾個用于實作版本控制的Bean
第一個版本的 Bean
@Data
@AllArgsConstructor
public class StudentV1 {
private String name;
}
第二個版本的 Bean
@Data
public class StudentV2 {
private Name name;
}
StudentV2使用的Name實體
@Data
@AllArgsConstructor
public class Name {
private String firstName;
private String lastName;
}
Restful 版本控制的方法
我們希望建立兩個版本的服務,一個傳回 StudentV1,另一個傳回 StudentV2。
讓我們來看看建立相同服務版本的4種不同方法。
通過 URI 進行版本控制
@RestController
public class StudentUriController {
@GetMapping("v1/student")
public StudentV1 studentV1() {
return new StudentV1("javadaily");
}
@GetMapping("v2/student")
public StudentV2 studentV2() {
return new StudentV2(new Name("javadaily", "JAVA日知錄"));
}
}
請求:
http://localhost:8080/v1/student
響應:{"name":"javadaily"}
http://localhost:8080/v2/student
響應:{"name":{"firstName":"javadaily","lastName":"JAVA日知錄"}}
通過請求參數進行版本控制
版本控制的第二種方法是使用請求參數來區分版本。請求示例如下所示:
-
http://localhost:8080/student/param?version=1
-
http://localhost:8080/student/param?version=2
實作方式如下:
@RestController
public class StudentParmController {
@GetMapping(value="/student/param",params = "version=1")
public StudentV1 studentV1() {
return new StudentV1("javadaily");
}
@GetMapping(value="/student/param",params = "version=2")
public StudentV2 studentV2() {
return new StudentV2(new Name("javadaily", "JAVA日知錄"));
}
}
http://localhost:8080/student/param?version=1
http://localhost:8080/student/param?version=2
通過自定義Header進行版本控制
版本控制的第三種方法是使用請求頭來區分版本,請求示例如下:
-
http://localhost:8080/student/header
-
- headers=[X-API-VERSION=1]
-
http://localhost:8080/student/header
-
- headers=[X-API-VERSION=2]
實作方式如下所示:
@RestController
public class StudentHeaderController {
@GetMapping(value="/student/header",headers = "X-API-VERSION=1")
public StudentV1 studentV1() {
return new StudentV1("javadaily");
}
@GetMapping(value="/student/header",headers = "X-API-VERSION=2")
public StudentV2 studentV2() {
return new StudentV2(new Name("javadaily", "JAVA日知錄"));
}
}
下圖展示了我們如何使用Postman執行帶有請求頭的Get請求方法。
http://localhost:8080/student/header
header:
X-API-VERSION = 1
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SM1EjN0UDOxEWMwE2MjZTOlRjN0YzMhhjM1AzY5EjNz8CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
http://localhost:8080/student/header
X-API-VERSION = 2
通過媒體類型進行版本控制
最後一種版本控制方法是在請求中使用Accept Header,請求示例如下:
-
http://localhost:8080/student/produce
-
-
headers=[Accept=application/api-v1+json]
-
-
http://localhost:8080/student/produce
-
-
headers=[Accept=application/api-v2+json]
-
@RestController
public class StudentProduceController {
@GetMapping(value="/student/produce",produces = "application/api-v1+json")
public StudentV1 studentV1() {
return new StudentV1("javadaily");
}
@GetMapping(value="/student/produce",produces = "application/api-v2+json")
public StudentV2 studentV2() {
return new StudentV2(new Name("javadaily", "JAVA日知錄"));
}
}
下圖展示了我們如何使用Postman執行帶有請求Accept的Get方法。
http://localhost:8080/student/produce
Accept = application/api-v1+json
http://localhost:8080/student/produce
Accept = application/api-v2+json
影響版本選擇的因素
以下因素影響版本控制的選擇
- URI 污染 - URL版本和請求參數版本控制會污染URI空間。
- 濫用請求頭 - Accept 請求頭并不是為版本控制而設計的。
- 緩存 - 如果你使用基于頭的版本控制,我們不能僅僅基于URL緩存,你需要考慮特定的請求頭。
- 是否能在浏覽器直接執行 ? - 如果您有非技術消費者,那麼基于URL的版本将更容易使用,因為它們可以直接在浏覽器上執行。
- API文檔 - 如何讓文檔生成了解兩個不同的url是同一服務的版本?
事實上,并沒有完美的版本控制解決方案,你需要根據項目實際情況進行選擇。
下面清單展示了主要API提供商使用的不同版本控制方法:
- 媒體類型的版本控制
-
- Github
- 自定義Header
-
- Microsoft
- URI路徑
-
- Twitter,百度,知乎
- 請求參數控制
-
- Amazon
以上,希望對你有所幫助!