一、简介

内容类型指示如何解释请求/响应中存在的数据。每当控制器收到 Web 请求时,它就会消耗或生成一些媒体类型。在此请求-响应模型中,可以使用/生成多种媒体类型,JSON 就是其中之一。

在这个快速教程中,我们将探索使用 Spring Boot 在 Spring MVC 中设置内容类型的不同方法。

2.Spring中的 @RequestMapping

简单来说, @RequestMapping 是一个重要的注解,它将Web请求映射到Spring控制器。它具有各种属性,包括 HTTP 方法、请求参数、标头和媒体类型。

一般来说,媒体类型分为两类:可消耗的和可生产的。除了这些之外,我们还可以在 Spring 中定义自定义媒体类型主要目的是将主要映射限制为我们的请求处理程序的媒体类型列表。

2.1.耗材类型

使用 Consumers 属性,我们可以指定控制器将从客户端接受的媒体类型。我们也可以提供媒体类型列表。让我们定义一个简单的端点:

@RequestMapping(value = "/greetings", method = RequestMethod.POST, consumes="application/json")
public void addGreeting(@RequestBody ContentType type, Model model) {
    // code here
}

如果客户端指定了无法被资源消耗的媒体类型,系统将生成 HTTP“415 不支持的媒体类型”错误。

2.2.可制作的媒体类型

Consumers 属性相反, Produces 指定资源可以生成并发送回客户端的媒体类型。毫无疑问,我们可以使用选项列表。 如果资源无法生成所请求的资源,系统将生成 HTTP“406 Not Acceptable”错误。

让我们从公开 JSON 字符串的 API 的简单示例开始。

这是我们的端点:

@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 来休息控制器

如果我们使用 Spring Boot 作为其余控制器,那么通过处理多个事情的单个注释将使我们的生活变得轻松。 @RestController 注释将 @Controller@ResponseBody 注释合并为一个注释。这将应用于该类中定义的所有端点。

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.使用 响应实体

@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

curl 命令返回 JSON 响应:

{ "test": "Hello from map" }

4。结论

在本文中,我们学习了如何使用 Spring boot 在 Spring MVC 中设置内容类型,首先是类路径中的默认 Json 映射器,然后使用 ResponseEntity,最后将返回类型从 String 更改为 Map。

与往常一样,所有代码片段都可以在 GitHub 上找到。