1. 引言
內容類型指示請求/響應中數據的解釋方式。當控制器接收到 Web 請求時,它會消費或產生某些媒體類型。在請求-響應模型中,可以消費/產生多種媒體類型,JSON 只是其中之一。
在本快速教程中,我們將探索在 Spring Boot 中設置內容類型的不同方法。
2. `@RequestMapping</em/> 在 Spring 中的使用
Simply put, <em/>@RequestMapping</em/> 是一個重要的註解,用於將 Web 請求映射到 Spring 控制器。它具有多種屬性,包括 HTTP 方法、請求參數、頭信息和媒體類型。
Generally, media types 歸類為可消耗型和可生成型。此外,我們還可以定義自定義媒體類型在 Spring 中。`其主要目的是限制主映射到一組媒體類型,以便為我們的請求處理器進行約束。</strong/>
2.1. 可消費媒體類型
通過 <em >consumes </em > 屬性,我們可以指定控制器將從客户端接受的媒體類型。 還可以提供媒體類型的列表。 讓我們定義一個簡單的端點:
@RequestMapping(value = "/greetings", method = RequestMethod.POST, consumes="application/json")
public void addGreeting(@RequestBody ContentType type, Model model) {
// code here
}如果客户端指定了無法由資源消費的媒體類型,系統將生成 HTTP “415 Unsupported Media Type” 錯誤。
2.2. 可生產媒體類型
與 <em>consumes</em> 屬性不同,<em>produces</em> 屬性指定資源可以生產並返回給客户端的媒體類型。 毫無疑問,我們可以使用一個選項列表。 如果資源無法生產請求的資源,系統將生成 HTTP “406 Not Acceptable” 錯誤。
讓我們從一個簡單的示例開始,API 暴露一個 JSON 字符串。
以下是我們的端點:
@GetMapping(
value = "/greetings-with-response-body",
produces="application/json"
)
public String getGreetingWhileReturnTypeIsString() {
return "{\"test\": \"Hello\"}";
}我們將會使用 CURL 進行測試:
curl http://localhost:8080/greetings-with-response-body上述命令會產生以下響應:
{ "test": "Hello" }3. 使用 Spring Boot 構建 REST 控制器
如果使用 Spring Boot 構建 REST 控制器,它將通過一個單一註解簡化我們的開發流程。<em><strong>@RestController</strong></em> 註解將 <em><strong>@Controller</strong></em> 和 <em><strong>@ResponseBody</strong></em> 註解合併為一個。該註解將應用於該類中定義的的所有端點。
3.1. 使用 @RestController 註解
Jackson 的 ObjectMapper 類解析來自字符串、流或文件的 JSON 數據。如果 Jackson 在類路徑上,Spring 應用中的任何控制器默認會渲染 JSON 響應。
我們將添加一個單元測試來驗證響應:
@Test
public void givenReturnTypeIsString_whenJacksonOnClasspath_thenDefaultContentTypeIsJSON()
throws Exception {
// Given
String expectedMimeType = "application/json";
// Then
String actualMimeType = this.mockMvc.perform(MockMvcRequestBuilders.get("/greetings-with-response-body", 1))
.andReturn().getResponse().getContentType();
Assert.assertEquals(expectedMimeType, actualMimeType);
}3.2. 使用 ResponseEntity
與 @ResponseBody 相比,ResponseEntity 是一種通用的類型,它代表整個 HTTP 響應。因此,我們可以控制其中包含的所有內容:狀態碼、頭信息和響應體。
讓我們定義一個新的端點:
@GetMapping(
value = "/greetings-with-response-entity",
produces = "application/json"
)
public ResponseEntity<String> getGreetingWithResponseEntity() {
final HttpHeaders httpHeaders= new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<String>("{\"test\": \"Hello with ResponseEntity\"}", httpHeaders, HttpStatus.OK);
}在我們的瀏覽器開發者控制枱中,我們可以看到以下響應:
{"test": "Hello with ResponseEntity"}我們將會通過測試用例驗證響應的內容類型:
@Test
public void givenReturnTypeIsResponseEntity_thenDefaultContentTypeIsJSON() throws Exception {
// Given
String expectedMimeType = "application/json";
// Then
String actualMimeType = this.mockMvc.perform(MockMvcRequestBuilders.get("/greetings-with-response-entity", 1))
.andReturn().getResponse().getContentType();
Assert.assertEquals(expectedMimeType, actualMimeType);
}
3.3. 使用 Map<String, Object> 返回類型
最後,但並非最不重要,我們還可以通過將返回類型從 String 更改為 Map 來設置內容類型。 此 Map 返回類型需要進行序列化,並返回一個 JSON 對象。
以下是我們的新端點:
@GetMapping(
value = "/greetings-with-map-return-type",
produces = "application/json"
)
public Map<String, Object> getGreetingWhileReturnTypeIsMap() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("test", "Hello from map");
return map;
}讓我們看看它的實際效果:
curl http://localhost:8080/greetings-with-map-return-type<p>使用 curl 命令返回 JSON 響應。</p>
{ "test": "Hello from map" }4. 結論
在本文中,我們學習瞭如何在 Spring Boot 中使用 Spring MVC 設置內容類型的方法。首先,我們使用了 classpath 中默認的 JSON 映射器,然後使用 ResponseEntity,最後將返回類型從 String 修改為 Map。