1. 概述
本教程將介紹如何定義自定義媒體類型並使用 Spring REST 控制器生成它們。
使用自定義媒體類型的良好應用場景是 API 版本控制。
2. API – 版本 1
讓我們從一個簡單的示例開始——一個通過 ID 暴露單個資源的 API。
我們將從我們向客户端暴露的資源的版本 1 開始。為了做到這一點,我們將使用自定義 HTTP 標頭——<em “application/vnd.baeldung.api.v1+json”</em>>。
客户端將通過 <em “Accept”</em> 標頭請求此自定義媒體類型。
以下是我們的簡單端點:
@RequestMapping(
method = RequestMethod.GET,
value = "/public/api/items/{id}",
produces = "application/vnd.baeldung.api.v1+json"
)
@ResponseBody
public BaeldungItem getItem( @PathVariable("id") String id ) {
return new BaeldungItem("itemId1");
}請注意此處出現的 produces 參數,它指定了該 API 可以處理的自定義媒體類型。
現在,BaeldungItem 資源 – 具有單個字段 – itemId:
public class BaeldungItem {
private String itemId;
// standard getters and setters
}最後但凡一課,我們來為該端點編寫一個集成測試:
@Test
public void givenServiceEndpoint_whenGetRequestFirstAPIVersion_then200() {
given()
.accept("application/vnd.baeldung.api.v1+json")
.when()
.get(URL_PREFIX + "/public/api/items/1")
.then()
.contentType(ContentType.JSON).and().statusCode(200);
}3. API – 版本 2
現在我們假設需要通過我們的資源更改向客户端暴露的詳細信息。
我們之前暴露了一個原始 ID – 現在我們需要隱藏它,並暴露一個名稱,以獲得更大的靈活性。
請務必理解,這種更改與之前的版本不兼容,本質上是一個破壞性更改。
以下是我們的新資源定義:
public class BaeldungItemV2 {
private String itemName;
// standard getters and setters
}因此,我們需要做的就是 – 將我們的 API 遷移到第二個版本。
我們將通過 創建我們自定義媒體類型的下一版本並定義一個新的端點來實現這個目標:
@RequestMapping(
method = RequestMethod.GET,
value = "/public/api/items/{id}",
produces = "application/vnd.baeldung.api.v2+json"
)
@ResponseBody
public BaeldungItemV2 getItemSecondAPIVersion(@PathVariable("id") String id) {
return new BaeldungItemV2("itemName");
}因此,我們現在擁有相同的端點,但它能夠處理新的 V2 操作。
當客户端請求 時 – Spring 將委託給舊操作,客户端將收到一個帶有 itemId 字段的 BaeldungItem (V1)。
但是,當客户端現在將 Accept 標頭設置為 時 – 他們將正確地命中新的操作,並獲得帶有 itemName 字段的資源 (V2):
@Test
public void givenServiceEndpoint_whenGetRequestSecondAPIVersion_then200() {
given()
.accept("application/vnd.baeldung.api.v2+json")
.when()
.get(URL_PREFIX + "/public/api/items/2")
.then()
.contentType(ContentType.JSON).and().statusCode(200);
}請注意,測試與該測試相似,但使用了不同的 請求頭。
4. 在類級別自定義媒體類型
最後,我們來討論一下在類級別定義媒體類型的可能性——這同樣也是可行的:
@RestController
@RequestMapping(
value = "/",
produces = "application/vnd.baeldung.api.v1+json"
)
public class CustomMediaTypeController正如預期的那樣,@RequestMapping 註解可以輕鬆應用於類級別,並允許我們指定 value、produces 和 consumes 參數。
5. 結論
本文闡述了在定義自定義媒體類型時,這對於版本公共 API 具有重要意義。