Spring 中的 API 版本控制

工程 | Rossen Stoyanchev | 2025年9月16日 | ...

在這篇“通往 GA 之路”系列的第二篇部落格文章中,我將重點介紹 Spring Framework 7 中即將推出的 API 版本控制支援,該系列旨在強調 Spring 組合中將於 11 月釋出的下一個主要版本中的主要功能。

引言

API 版本控制是一個具有挑戰性的話題。大多數文章列出了各種實現方式,但沒有提供建議。當提供建議時,範圍廣泛。例如,Roy Fielding建議反對。它是一種常見且廣泛使用的實踐,但關於如何做或是否做,卻沒有標準或共識。

此外,不同的應用有不同的需求,這些需求取決於業務領域、公司動態、演進階段等,因此需要考慮已釋出的建議如何適用於您自己的特定情況。

所有這些,再加上透過 @RequestMapping 註解表達各種方式(路徑、頭部、媒體型別等)並不太難,實際上意味著 Spring 之前沒有官方支援,直到現在。發生了什麼變化?

正如新功能通常的情況一樣,它們始於使用者請求,這次請求指出,雖然在 Spring 應用程式中實現 API 版本控制是可能的,但實際上需要大量工作。回顧總括問題的子任務,這確實是一個有效的觀點。自那時起我們在這個話題上看到的反饋和興趣數量進一步表明了明確的需求。

這篇博文的目的不是進一步討論 API 版本控制實踐。有關該主題的更長介紹,您可以觀看我在今年早些時候的 Spring I/O 會議上的演講。

通常,此功能的目的是為這種非常常見的實踐和需求提供必要的構建塊。

伺服器處理

伺服器端處理的核心是 ApiVersionStrategy,這是一個關鍵契約,它瞭解所有應用程式的 API 版本控制偏好。它可以解析、分析和驗證請求版本;它瞭解支援的版本範圍;並且可以幫助在響應中傳送棄用提示。

您可以透過MVC 配置WebFlux 配置來配置它。例如

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

	@Override
	public void configureApiVersioning(ApiVersionConfigurer configurer) {
		configurer.useRequestHeader("API-Version");
	}
}

對於 Spring Boot 應用程式,有等效的屬性。例如

spring.mvc.apiversion.use.header=API-Version

一旦配置完成,它就可以用於在請求處理中支援 API 版本控制。

對於帶註解的控制器,您可以使用 @RequestMapping 註解的新 version 屬性及其專用形式,例如 @GetMapping

@RestController
public class AccountController {

	@GetMapping(path = "/account/{id}", version = "1.1") 
	public Account getAccount() {
	}
}

對於函式式端點,您可以使用 version 請求謂詞

RouterFunction<ServerResponse> route = RouterFunctions.route()
	.GET("/hello-world", version("1.2"),
		request -> ServerResponse.ok().body("Hello World")).build();

如果 API 版本位於請求頭、查詢引數或媒體型別中,則在對映中無需做任何其他事情。

如果 API 版本位於路徑中,則必須將其宣告為 URI 變數(可以使用任何名稱),例如“/api/{version}”。通常,最好透過路徑匹配選項將其作為所有處理程式的通用路徑字首進行外部配置,這樣就不需要在每個對映中重複它。

預設情況下,請求版本被解析為包含主版本、次版本和補丁值的語義版本,如果次版本和補丁版本不存在,則設定為 0。這對於能夠比較版本很重要。如果您想使用日期或任何其他格式,可以自定義或替換解析器。

在對映中,版本可以是固定版本,例如“1.2”,也可以是基線版本,例如“1.2+”。基線版本在以下場景中非常有用:增量更改應用於選定的端點,從而無需為未更改的端點建立額外的控制器方法。

例如,給定支援的版本“1.2”和“1.3”,版本為“1.2+”的控制器方法同時支援這兩個版本。這允許控制器方法在版本 1.3 和其他未來版本中繼續工作,直到在更高版本中需要新的控制器方法。

版本控制的一個重要方面是向客戶端提供棄用提示。您可以配置一個棄用處理器來完成此操作。內建處理器可以根據 RFC 9745RFC 8594 設定“Deprecation”、“Sunset”和“Link”頭。

客戶端支援

從客戶端的角度來看,您可能需要使用 API 版本執行請求。為此,有一個 ApiVersionInserter,它決定如何一次將版本插入請求中,隨後當您發出請求時,您只需指定版本值。

例如,在 RestClientWebClient 中,您可以設定一個插入器

RestClient client = RestClient.builder()
		.baseUrl("https://:8080")
		.apiVersionInserter(ApiVersionInserter.useHeader("API-Version"))
		.build();

對於 Spring Boot 應用程式,有等效的屬性。例如

spring.http.client.restclient.apiversion.insert.header=API-Version

然後按如下方式執行請求

Account account = client.get().uri("/accounts/1")
		.apiVersion(1.1)
		.retrieve()
		.body(Account.class);

HTTP 介面客戶端透過 @HttpExchange 註解的新 version 屬性及其專用形式(例如 @GetExchange 等)支援 API 版本控制。例如

@HttpExchange("/accounts")
public interface AccountService {

	@GetExchange(url = "/{id}", version = "1.1")
	Account getAccount(@PathVariable int id);

}

測試

正如您所料,API 版本控制也適用於測試,例如與 RestTestClient(7.0 版新增)和 WebTestClient 一起使用。

兩者都是實際的客戶端,類似於 RestClientWebClient,因此需要配置客戶端 ApiVersionInserter 以相應地準備請求。它們還配置伺服器端,但這取決於所選的設定,如下所示

在不使用測試客戶端的情況下直接使用 MockMvc 進行測試時,也支援 API 版本控制。您可以配置 ApiVersionInserter 來初始化 MockHttpServletRequest,並在使用獨立設定時配置 ApiVersionStrategy

如果您想在 Spring Boot 測試場景中檢視上述一些內容,請檢視此示例專案中的測試

總結

在這篇博文中,我們簡要介紹了 Spring Framework 7 中即將推出的 API 版本控制支援。

有關更多詳細資訊,請查閱參考文件的相關部分。您還可以嘗試這個示例專案

如果您有 API 版本控制要求,請檢視並在此處或透過我們的問題跟蹤器聯絡我們(如果需要)。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有