controller 에서 게시글 작성부분을 보면서 테스트를 진행해봤다.
아래의 두 코드는 PostRequestDto 에 @RequestBody / @ModelAttribute 를 사용하는 것의 차이다.
// 게시글 작성
@PostMapping
public ResponseEntity<PostResponseDto> createPost(@RequestPart(value = "image", required = false) MultipartFile multipartFile, @RequestBody PostRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok(postService.createPost(multipartFile, requestDto, userDetails.getUser()));
}
@Getter
@AllArgsConstructor
public class PostRequestDto {
private String title;
private String contents;
private String username;
}
이미지 파일과 json 형태로 데이터를 전송했으나, 실패했다.
그러나 JSON 형태로 따로 보내줄 경우, 정상적으로 데이터가 반환되었다.
물론, 이미지 파일이 같이 전송되지는 않았다.
// 게시글 작성
@PostMapping
public ResponseEntity<PostResponseDto> createPost(@RequestPart(value = "image", required = false) MultipartFile multipartFile, @ModelAttribute PostRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
return ResponseEntity.ok(postService.createPost(multipartFile, requestDto, userDetails.getUser()));
}
@Getter
@AllArgsConstructor
public class PostRequestDto {
private String title;
private String contents;
private String username;
}
이미지와 함께 fom-data 형식으로 데이터를 전송했고, 정상적으로 반환되었다.
이는 @ModelAttribute 가 JSON 객체를 받아올 수 있기 때문이다.
단, body 에 데이터를 담을 경우엔 Content-Type 을 application/json 이 아닌 multipart/form-data 형태로 전송해야 한다.
참고: @RequestParam VS @ModelAttribute
form-data 형태인 이미지 파일(MultipartFile)과 JSON 데이터를 함께 전송하기 위해, json 데이터를 @ModelAttribute 로 보낸 것이다.
1:1 로 받는다
파라미터 타입이 잘못 들어오면, 400 Bad Request 를 날린다
생략 가능
name과 age라는 파라미터에 값을 담아서 전송했더니, 올바르게 @ResponseBody를 거쳐 올바르게 JSON형식으로 값이 담겨서 왔다.
Java의 객체로 데이터를 받아올 수 있다.
타입 변환에 실패하더라도, 작업은 계속 진행된다
생략 가능
parameter에 넣은 값들이 올바르게 JSON형식으로 Body에 반환
값이 담기지 않았다.
@ModelAttribute 에서 Body를 이용해 전송하려면, Content-Type 을 application/json 이 아닌 multipart/form-data 형태로 전송해야 하기 때문이다.
name과 age에 값이 담겨서 반환
아래는 요청을 보내는 Dto 클래스다.
Controller 에서 @ModelAttribute 로 값을 넘길 때, 이 Dto 클래스에서는 어떤 어노테이션을 사용하면 좋을까.
public class PostRequestDto {
private String title;
private String contents;
private String username;
}
@ModelAttribute 는 요청 파라미터를 해당 메소드의 매개변수로 전달하거나 모델에 바인딩하는 데 사용한다.
생성자가 1개면, 그 생성자를 통해 객체를 생성
생성자가 2개 이상이면, 매개변수 없는 생성자를 통해 객체를 생성하고 Setter 로 값을 세팅
@ModelAttribute 를 통해, NULL 이 아닌 값을 입력받고 싶을 경우, 다음 2가지 방식을 사용할 수 있다.
@Getter
@AllArgsConstructor
public class PostRequestDto {
private String title;
private String contents;
private String username;
}
@AllArgsConstructor 만 사용
@AllArgsConstructor
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PostRequestDto {
private String title;
private String contents;
private String username;
}
@NoArgsConstructor 이 있다면, @Setter 를 반드시 붙이자.
AllArgsConstructor 와 NoArgsConstructor 를 같이 사용할 경우,
NoArgsConstructor 이 객체를 생성하게 된다. 따라서, 이 땐 Setter 가 필요하게 된다.
@NoArgsConstructor
참고: [Spring] @RequestParam, @RequestBody, @ModelAttribute의 차이
참고: [Spring Boot] @ModelAttribute 객체값 Null일때 해결방법
참고: [Spring] AllArgsConstructor가 있는데 왜 @ModelAttribute 객체에 값이 할당되지 않는걸까? (feat. ModelAttributeMethodProcessor의 코드를 뜯어보자)
좋은 글 감사합니다!