package hello.springmvc.basic.request;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/total-study2")
@RestController
@Slf4j
public class TotalStudy2 {
// 디스패쳐서블렛이 RUN 해주는 놈이다.
// 이 클래스의 각 메서드들은 컨트롤러이다. 컨트롤러는 핸들러매핑으로 RequestMappingHandlerMapping 을 사용한다.
//
// 1. 핸들러 매핑: 입력받은 url 을 통해(RequestMappingHandlerMapping) 또는 스프링 빈중에서 @RequestMapping 이 붙은 핸들러(여기선 메서드)를 찾는다.
//
// 2. requestMapping 이니까 RequestMappingHandlerAdapter 실행 (어댑터를 확실히 알고있자), 이 어댑터는 ArgumentResolver 를 호출한다.
//
// 3. 핸들러의 파라미터들을 보고 ArgumentResolver 작동한다. 파라미터에 해당하는 (@RequestParam 이나 @ModelAttribute, request 같은) 값들을 생성해준다.
// 만약 @RequestBody 쓴다면 메세지 컨버터 까지 작동한다.
//
// 4. 컨트롤러에서 return 값은 모델앤뷰, 스트링을 통한 뷰, 그냥 스트링(@ResponseBody) 다 가능한데 ReturnValueHandler 이 작동되기 때문이다.
// 만약 @ResponseBody 를 통해 return 한다면 메세지 컨버터 까지 작동한다.
//
// 메세지 컨버터는 @RequestBody 와 @ResponseBody 두 경우에 호출된다. RequestResponseBodyMethodProcessor (ArgumentResolver) 를 사용한다.
//
// @ResponseBody: viewResolver 대신 HttpMessageConverter 동작
//
// String, Integer, int 같은 자료형들은 ArgumentsResolver 에 의하여 기본적으로 @RequestParam 객체를 생성한다.
// 하지만 HelloData 같은 클래스 객체를 만나면 @ModelAttribute 객체를 생성한다.
// 그래서 json 사용시 @RequestBody 를 생략하면 @ModelAttribute 로 잘못 생성된다.
@GetMapping
@RequestMapping("/requestParm")
public String paramRequest(@RequestParam(defaultValue = "de") String name,
@RequestParam(defaultValue = "0") int age,
@RequestHeader("accept") String accept) {
log.info("name = {}, age = {}, accept = {}", name, age, accept);
return "v1";
}
@PostMapping
@RequestMapping("/requestParm2")
public String paramRequest2(@RequestParam(defaultValue = "de") String name,
@RequestParam(defaultValue = "0") int age,
@RequestHeader("content-type") String content) {
log.info("name = {}, age = {}, content = {}", name, age, content);
return "v2";
}
@PostMapping
@RequestMapping("/modelAttribute")
public String modelAttribute(@ModelAttribute Info info) {
log.info("name = {}, age = {}", info.getName(), info.getAge());
return "v3";
}
// StringHttpMessageConverter 작동
@PostMapping
@RequestMapping("/messageBody")
public String messageBody(@RequestBody String messageBody, @RequestHeader("content-type") String content,
@RequestHeader("accept") String accept) {
log.info("messageBody = {}", messageBody);
log.info("content = {} aceept = {}", content, accept);
return "v4";
}
// MappingJackson2HttpMessageConverter 작동
// 요청 HTTP 의 컨텐트 타입 : 모두 가능
// 요청 HTTP 의 accept : text/plain 가능해야함
@PostMapping
@RequestMapping("/json1")
public String json1(@RequestBody Info info, @RequestHeader("content-type") String content,
@RequestHeader("accept") String accept) {
log.info("name = {} age = {}", info.getName(), info.getAge());
log.info("content = {} accept = {}", content, accept);
return "v4"; // 반환 HTTP 의 content-type : text/plain, 리턴 밸류 핸들러에서 메세지컨버터 호출 시 StringHttpMessageConverter 작동
}
// MappingJackson2HttpMessageConverter 작동
// 요청 HTTP 의 컨텐트 타입 : application/json 만 가능
// 요청 HTTP 의 accept : application/json 가능해야함
@PostMapping
@RequestMapping("/json2")
public Info json2(@RequestBody Info info, @RequestHeader("content-type") String content,
@RequestHeader("accept") String accept) {
log.info("name = {} age = {}", info.getName(), info.getAge());
log.info("content = {} accept = {}", content, accept);
return info; // 반환 HTTP 의 content-type : application/json, 리턴 밸류 핸들러에서 메세지컨버터 호출 시 MappingJackson2HttpMessageConverter 작동
}
@Data
static class Info {
private String name;
private int age;
}
}