@ResponseBody , @RequestBody
@RequestBody 를 통해서 자바 객체로 Conversion 을 할때 그냥 변환되는것이 아니라 HttpMessageConverter 를 사용하는데 아래의 메서드에 각종의 메시지 컨버터가 설정되어 있다.
WebMvcConfigurationSupport.addDefaultHttpMessageConverters
만약 요청이 JSON으로 들어온 경우 요청 해더(request header)에 컨텐츠 타입(Content-Type)을 알려줘야 한다. 그러면 헤더에 있는 컨텐츠 타입을 보고 JSON을 컨버팅 할 수 있는 컨버터(Jackson2ObjectMapperBuilder)를 사용하겠다고 JSON을 자바 객체로 변환하는 메시지 컨버터를 사용하여 본문에 담긴 데이터를 자바 객체로 변환하게 된다.
/* @RequestBody를 통해 자바 객체로 변환할때 HttpMessageConverter를 사용하여
* 헤더에 담긴 컨텐츠 타입을 보고 어떤 메시지 컨버터를 사용할 것인지 판단하여
* 요청 본문에 담긴 값을 자바 객체로 변환한다
*/
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
Jackson2ObectMapperBuilder는 스프링부트에서 JacksonAutoConfiguration클래스에서 자동으로 설정하기 때문에 별다른 설정없이 JSON을 자바객체로 변환하는 ObjectMapper를 사용 할 수 있다.
Jackson2ObjectMapperBuilder 내부를 보면 autoDetectGetterSetter() 라는 메서드를 사용하는데 이는 JSON 타입으로 변환하기 위한 객체(DTO)에 getter와 setter 메서드가 존재해야 한다는 것을 의미한다
public Jackson2ObjectMapperBuilder autoDetectGettersSetters(boolean autoDetectGettersSetters) {
this.features.put(MapperFeature.AUTO_DETECT_GETTERS, autoDetectGettersSetters);
this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters);
this.features.put(MapperFeature.AUTO_DETECT_IS_GETTERS, autoDetectGettersSetters);
return this;
}
만약 getter/setter가 존재하지 않으면 응답 메세지를 보낼때 Jackson2ObjectMapperBuilder를 제대로 사용하지 못해서 JSON 타입으로 변환이 처리되지 않기때문에 클라이언트에서 success()함수로 결과값을 받아 올 수 없다
static class Hello{
private String name;
// getter, setter ==> java bean 표준방식
// property 접근방식이라고도 한다
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
스프링 부트의 pom.xml을 보면 spring-boot-starter-web이 존재하는데 내부에 들어가보면 jackson-databind 의존성이 자동으로 잡혀있는것을 볼수 있다. 해당 의존성이 있어야 JSON 타입으로 제대로 변환이 된다.
@RequestBody 역할
이 어노테이션이 붙은 파라미터에는 http요청의 본문(body)가 그대로 전달된다.
HTTP요청의 바디내용을 통째로 자바객체로 변환해서 매핑된 메서드 파라미터로 전달해준다
@ResponseBoby 역할
자바객체를 HTTP요청의 바디 내용으로 매핑하여 클라이언트로 전송한다
@ResponseBOdy가 붙은 파라미터가 있으면 HTTP요청의 미디어타입과 파라미터의 타입을 먼저 확인한다
- dispatcher-servlet.xml의 <annotiation-drvien>태그 내에 선언하는 <message-converter>에서 확인
- 메세지 변환기중에서 해당 미디어 타입과 파라미터 타입을 처리할수 있다면 HTTP 요청의 본문 부분을 통째로 변환해서 지정된 메서드 파라미터로 전달해준다
즉 @ResposeBody 을 사용하면 http 요청 body를 자바 객체로 전달받을수 있다
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
@ResponseBody를 사용하면
- HTTP Body에 문자 내용을 직접 반환한다
- viewResolver 대신에 HttpMessageConverter가 동작한다
- 기본 문자처리는 StringHttpMessageConverter가 담당
- 기본 객체처리는 MappingJackson2HttpMessageConverter가 담당
- byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있다
MessageConverter의 종류
- StringHttpMessageConverter
- FormHttpMessageConverter
- ByteArrayMessageConverter
- MarshallingHttpMessageConverter
- SourceHttpMessageConverter
- BufferedImagedHttpMessageConverter
- MappingJacksonHttpMessageConverter
- Jackson's ObjectMappter 를 사용하여 request, response 를 JSON 으로 변환할때 사용되는 MessageConverter
- applicaton/json 을 지원한다.
@RestController
@Controller와는 다르게 RestController는 리턴값이 자동으로 @ResponseBody가 붙게되어 별도 어노테이션을 명시해주지 않아도 HTTP 응답데이터 body에 자바 객체가 매핑되어 전달된다
- @Controller인 경우에 body를 자바객체로 받기 위해서는 @ResponseBody 어노테이션을 반드시 붙여야한다
정리하면
클라이언트에서 서버로 필요한 데이터를 전송하기 위해서 JSON이라는 데이터를 요청 본문에 담아서 서버로 보내면, 서버에서는 @RequestBody 어노테이션을 사용하여 http 요청 본문에 담긴 값들을 자바 객체로 변환시켜 객체에 저장한다.
서버에서 클라이언트로 응답 데이터를 전송하기 위해서 @ResponseBody를 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하여 클라이언트로 전송한다