Http 요청파라미터-@ModelAttribute
요청된 파라미터 처리 - @ModelAttribute
실제 개발을 하면 요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야한다.
보통 다음과 같은 코드를 작성할 것이다.
@RequestParam String username;
@RequestParam int age;
HelloData data = new HelloData();
data.setUsername(username);
data.setAge(age);
스프링은 이 과정을 완전히 자동화해주는 @ModelAttribute 기능을 제공한다.
먼저 요청 파라미터를 바인딩 받을 객체를 만들자 (bind의 사전적의미 = 묶다)
바인딩 받을 객체 HelloData
@Data // @Getter , @Setter , @ToString , @EqualsAndHashCode , @RequiredArgsConstructor 를 자동으로 적용해주는 어노테이션이다.
public class HelloData {
private String username;
private int age;
}
@ToString은 객체를 출력하기위한 toString을 오버라이드해서 더 깔끔하게 자동으로 만들어준다.
@Model 안의 @EqualsAndHashCode는 무엇일까?
@RequestParam을 이용했으면 다음과 같이 파라미터를 받아 객체를 생성하고 사용했을것이다
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(
@RequestParam String username,
@RequestParam int age) {
HelloData helloData = new HelloData();
helloData.setUsername(username);
helloData.setAge(age);
log.info("username = {} , age = {}", helloData.getUsername(), helloData.getAge());
log.info("@Tostring이 toString 메소드를 깔끔하게 오버라이드해줌 , {}", helloData.toString());
return "ok";
}
@ModelAttribute를 사용하게되면
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
log.info("username = {} , age = {}", helloData.getUsername(), helloData.getAge());
log.info("hellodata = {}", helloData.toString());
return "ok";
}
다음과 같이 @RequestParam으로 파라미터를 받아 변수에 넣고,
파라미터를 바인딩할 객체를 생성해서 값을 넣는 과정이 전부 사라진다.
1.요청 파라미터의 이름으로 Hellodata객체의 프로퍼티를 찾는다. ?username=a&age=10 이런식으로 들어왔다면
username과 age를 이용해서 찾는다.
2. 그리고 해당 프로퍼티의 setter를 호출해서 파라미터값을 입력(바인딩)해준다.
username으로 setUsername()을찾고 , age로 setAge()를 찾아 값을 넣어준다.
위와같이 Spring동작하므로 바인딩할 객체에는 Setter가 필수다!
(setter가 없으면 값이 들어가지않는다.)
객체의 어떤 객체변수(속성)가 getter와 setter 둘다 가졌다면 , 프로퍼티라고 부른다
프로퍼티의 읽기와 쓰기는 일반적으로 게터(getter)와 세터(setter) 메소드 호출로 변환된다.
@ModelAttribute의 생략
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(HelloData helloData) { //@ModelAttribute는 생략가능하다.
log.info("username = {} , age = {}", helloData.getUsername(), helloData.getAge());
log.info("hellodata = {}", helloData.toString());
return "ok";
}
@ModelAttribute는 생략할 수 있다.
그런데 @RequestParam도 생략가능하니까 혼란이 발생할 수 있다.
그래서 스프링은 생략시 다음과 같은 규칙을 적용한다.
1. String,int,Integer와 같은 단순타입은 @RequestParam을 적용하고
2. 나머지는 @ModelAttribute를 적용한다 ( 하지만 argument resolver로 지정해둔 타입은 @ModelAttribute가 적용되지않는다 ex) HttpServletResponse 이런애들이 적용되어있음)
여기까지가 요청된 파라미터의 대해 알아본것이다.
즉
GET 방식으로 들어오는 쿼리 파라미터와
POST방식으로 들어오는 HTML Form 방식의 파라미터에 대해
어떻게 받아서 처리하는지를 배운것이다.
이제부터는 Http message body에 데이터를 직접 담아서 요청온것을 처리하는법에 배운다.
Http요청 메시지 - 단순텍스트
V1 HttpServletRequest, Response 사용
http 메시지 바디를 통해 넘어온 데이터는 @RequestParam,@ModelAttribute를 사용할 수 없다.
(물론 HTML Form 형식은 쿼리파라미터형식으로 사용가능하다)
그리고 http 메시지 바디를 통해 데이터가 들어오므로 Http Method도 Post,Put,Patch를 사용한다.
(@PostMapping, @PutMapping, @PatchMapping)
GET방식으로도 Body를 받을 수 있지만 실무에서는 그렇게 사용하지않는다.
@Slf4j
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body-string-v1") //Http 메세지 Body에 값이 들어올것이므로 @PostMapping으로 받는다.
public void requestBodyString(HttpServletRequest request, HttpServletResponse response)
throws IOException {
ServletInputStream inputStream = request.getInputStream(); //request객체의 inputStream을 받고
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); //메시지의 바디를 받는다.
log.info("messageBody={}", messageBody);
response.getWriter().write("ok");
}
}
V2 InputStream,Writer 사용
Spring은 메소드 인자로 엄청 다양하게 지원하지만 그중에 InputStream과 Writer도 지원해준다.
parameter(파라미터) ==> 매개변수
매개변수는 함수를 정의할때 들어오는값을 설정하는 그게 파라미터(매개변수)
public void add(int a, int b) {
}
여기서는 a,b가 파라미터
argument ==> 전달인자
add(10,20); 이렇게하면 여기서는 10,20이 전달인자(argument)
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) //이렇게 원하는 전달인자를 받으면 된다.
throws IOException {
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
responseWriter.write("ok");
}
이런식으로 수정이되고, 잘 동작한다.
V3 HttpEntity, RequestEntity, ResponseEntity 사용
HttpEntity는 Http 헤더와 바디정보를 편하게 조회할 수 있는 객체이다! 파라미터와는 상관없음!
파라미터로 데이터가 들어오는 경우는 @RequestParam,@ModelAttribute를 이용한다.
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) // HttpEntity<String> 객체를 만들면 Http메시지바디에있는값을 "String"으로 바꿔준다.
throws IOException { // 반환도 HttpEntity<String>를 해준다, HttpEntity는 http메시지를 의미한다고 생각하면된다.
// String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); 이와같은코드가 HttpMessageConverter로인해 자동으로 진행됨
String body = httpEntity.getBody(); //들어온 Http메시지 바디의 값을 저장하고
log.info("messageBody={}", body); // 출력해보고
return new HttpEntity<>("ok"); //Http엔티티를 만들어 바디를 채워서 리턴해준다.
}
잘 동작한다.
헤더와 바디정보를 쉽게 조회할 수 있는 HttpEntity를 상속한
RequestEntity와 ResponseEntity가 있다.
RequestEntity는 헤더,바디정보 뿐만아니라 HttpMethod,URL 정보까지 조회가능하다. ( 요청에서 사용한다)
ResponseEntity는 헤더와 바디정보 뿐만 아니라 Http상태코드까지 설정이 가능하다. ( 응답에서 사용한다.)
RequestEntity는 요청받은 값들을 조회할때 사용
ResponseEntity는 응답에 대한 http응답메시지의 내부값들을 설정하고 반환할때 사용
RequestEntity,ResponseEntity 사용해보기
@PostMapping("/request-body-string-v3-2")
public ResponseEntity<String> requestBodyStringV3_2(RequestEntity<String> requestEntity)
throws IOException {
String method = requestEntity.getMethod().toString();
String type = requestEntity.getType().toString();
String URL = requestEntity.getUrl().toString();
String headers = requestEntity.getHeaders().toString();
String body = requestEntity.getBody();
System.out.println("method = " + method);
System.out.println("type = " + type);
System.out.println("URL = " + URL);
System.out.println("headers = " + headers);
System.out.println("body = " + body);
return new ResponseEntity<>("ok", HttpStatus.OK);//헤더도 넣을수있음
}
헤더를 넣거나 받을때는 MultiValueMap을 이용한다.
v4 - @ResponseBody, @RequestBody
@ResponseBody //해당 어노테이션이 있으면, 반환되는 문자열값을 http응답메시지 바디에 넣어준다.
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) { //@RequestBody 어노테이션을 이용하여 바디에 들어온값을 받을 수 있다.
//@RequestBody 어노테이션덕에 바디에 들어온 String값이 messageBody변수에 담긴다.
log.info("messageBody ={}", messageBody);
return "ok";
}
@RequestBody
@RequestBody를 사용하면 HTTP 메시지 바디 정보를 편리하게 조회할 수 있다.
참고로 헤더정보가 필요하다면 HttpEntity를 사용하거나, @RequestHeader를 사용하면 된다.
이렇게 메시지 바디를 직접 조회하는 기능은 요청 파라미터를 조회하는 @RequestParam,@ModelAttribute와 전혀 관계가 없다.
요청 파라미터 ==> PathVariable을 통해 들어오거나, 쿼리스트링형식으로 들어오는 값들
@ResponseBody
'인프런 > 스프링 MVC 1편' 카테고리의 다른 글
13)HTTP 응답 (정적리소스,뷰 템플릿) , Thymeleaf 스프링부트 설정 (0) | 2023.01.26 |
---|---|
12)HTTP요청 메시지 처리방법 [데이터타입 :JSON] (v1 ~ v4) (0) | 2023.01.26 |
10)HandlerMethodArgument,RequestParam 처리 방법들 (0) | 2023.01.25 |
9)요청매핑 (0) | 2023.01.20 |
8)스프링 MVC - 기본기능, 로깅(logging) (1) | 2023.01.19 |
댓글