1. 소개

콘텐츠 유형은 요청/응답에 있는 데이터를 해석하는 방법을 나타냅니다. 컨트롤러가 웹 요청을 수신할 때마다 일부 미디어 유형을 소비하거나 생성합니다. 이 요청-응답 모델에서는 여러 미디어 유형을 소비/생산할 수 있으며 JSON은 그 중 하나입니다.

이 빠른 사용방법(예제)에서는 Spring MVC에서 콘텐츠 유형을 설정하는 다양한 방법을 살펴봅니다.

2.  Spring의 @RequestMapping

간단히 말해서 @RequestMapping 은 웹 요청을 Spring 컨트롤러에 매핑하는 중요한 어노테이션입니다. HTTP 메서드, 요청 매개 변수, 헤더 및 미디어 유형을 비롯한 다양한 속성이 있습니다.

일반적으로 미디어 유형은 소비 가능한 것과 생산 가능한 두 가지 범주로 나뉩니다. 이 외에도 Spring에서 사용자 정의 미디어 유형을 정의할 수 있습니다 . 주요 목적은 요청 처리기에 대한 미디어 유형 List에 대한 기본 매핑을 제한하는 것입니다.

2.1. 소모성 미디어 유형

소비 속성을 사용 하여 컨트롤러가 클라이언트에서 수락할 미디어 유형을 지정할 수 있습니다. 미디어 유형 List도 제공할 수 있습니다. 간단한 Endpoints을 정의해 보겠습니다.

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

클라이언트가 리소스를 사용할 수 없는 미디어 유형을 지정하는 경우 시스템은 HTTP "415 지원되지 않는 미디어 유형" 오류를 생성합니다.

2.2. 생산 가능한 미디어 유형

Consumes 속성 과 달리 produce는 리소스가 생성 하여 클라이언트로 다시 보낼 수 있는 미디어 유형을 지정합니다. 의심할 여지 없이 옵션 List을 사용할 수 있습니다. 리소스가 요청한 리소스를 생성할 수 없는 경우 시스템은 HTTP "406 Not Acceptable" 오류를 생성합니다.

JSON 문자열을 노출하는 API의 간단한 예부터 시작하겠습니다.

엔드포인트는 다음과 같습니다.

@RequestMapping(
  value = "/greetings-with-response-body", 
  method = RequestMethod.GET, 
  produces="application/json"
) 
@ResponseBody
public String getGreetingWhileReturnTypeIsString() { 
    return "{\"test\": \"Hello using @ResponseBody\"}";
}

CURL을 사용하여 이를 테스트합니다.

AdChoices
광고
curl http://localhost:8080/greetings-with-response-body

위의 명령은 응답을 생성합니다.

{ "test": "Hello using @ResponseBody" }

헤더에 있는 콘텐츠 유형에 따라 @ResponseBody 는 메서드 반환 값을 웹 Response body에만 바인딩합니다.

3. Content-Type이 제대로 설정되지 않음

메서드에 반환 유형 문자열이 있고 클래스 경로에 JSON 매퍼가 없는 경우 반환 값은 콘텐츠 유형을 "텍스트/일반"으로 설정하는 StringHttpMessageConverter 클래스에서 처리합니다. 이로 인해 컨트롤러가 예상한 콘텐츠 유형을 생성할 수 없는 문제가 종종 발생합니다.

이 문제를 해결하기 위한 다양한 접근 방식을 살펴보겠습니다.

3.1. JSON 매퍼와 함께 @ResponseBody 사용

Jackson ObjectMapper 클래스 는 문자열, 스트림 또는 파일에서 JSON을 구문 분석합니다. Jackson이 클래스 경로에 있는 경우 Spring 애플리케이션의 모든 컨트롤러는 기본적으로 JSON 응답을 렌더링합니다.

AdChoices
광고

클래스 경로에 Jackson 을 포함하려면 pom.xml 에 다음 의존성을 추가해야 합니다 .

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.4</version>
</dependency>

응답에서 확인할 단위 테스트를 추가합니다.

@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 응답을 나타내는 일반 유형입니다. 결과적으로 상태 코드, 헤더 및 본문과 같이 포함되는 모든 것을 제어할 수 있습니다.

새 Endpoints을 정의해 보겠습니다.

@RequestMapping(
  value = "/greetings-with-response-entity",
  method = RequestMethod.GET, 
  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"}

ResponseEntity 를 사용하면 디스패처 서블릿 에 어노테이션 기반 태그가 있어야 합니다 .

<mvc:annotation-driven />

간단히 말해서, 위의 태그는 Spring MVC 의 내부 작업에 대한 더 큰 제어를 제공합니다 .

테스트 사례를 사용하여 응답의 콘텐츠 유형을 확인합니다.

@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 객체를 반환합니다.

새로운 엔드포인트는 다음과 같습니다.

@RequestMapping(
  value = "/greetings-with-map-return-type", 
  method = RequestMethod.GET, 
  produces = "application/json"
)
@ResponseBody
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. 결론

이 기사에서는 먼저 클래스 경로에 Json 매퍼를 추가한 다음 ResponseEntity를 사용하고 마지막으로 리턴 유형을 String에서 Map으로 변경하여 Spring MVC에서 컨텐츠 유형을 설정하는 방법을 배웠습니다.

항상 그렇듯이 모든 코드 스니펫은 GitHub 에서 찾을 수 있습니다 .

Generic footer banner