desirialization : json -> 객체로 변환
serialization : 객체 -> json으로 변환
입력값으로 객체보다 추가적인 데이터까지 같이 주면?
○ Bad_Request로 응답 vs 받기로 한 값 이외는 무시아래 옵션을 사용 할 지는 좀 더 생각 해 보자.
#application.properties
#ObjectMapper 커스터마이징
#desirialization 할 때 binding 할 프로퍼티가 존재 하지 않으면 실패 처리
#Bad Request 처리 시 사용
spring.jackson.deserialization.fail-on-unknown-properties=true
@Valid와 BindingResult (또는 Errors)
● BindingResult는 항상 @Valid 바로 다음 인자로 사용해야 함. (스프링 MVC)
● @NotNull, @NotEmpty, @Min, @Max, ... 사용해서 입력값 바인딩할 때 에러 확인할
수 있음
handler method 구현
@Valid EventDto eventDto // dto 객체를 검증한다.
// 에러 확인 후 존재하면 에러 코드를 돌려준다.
if(errors.hasErrors()){
return ResponseEntity.badRequest().build();
}
@PostMapping
public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto , Errors errors) {
// 에러 확인 후 존재하면 에러 코드를 돌려준다.
if(errors.hasErrors()){
return ResponseEntity.badRequest().build();
}
/**
* modelmapper를 이용해서 dto의 값을 domain객체에 값 복사 해 준다.
*/
Event event = modelMapper.map(eventDto,Event.class);
Event newEvent = eventRepository.save(event);
URI uri = linkTo(EventContoller.class).slash(newEvent.getId()).toUri();
return ResponseEntity.created(uri).body(event); // ResponseEntity를 사용하여 header 정보 등록
}
DTO 객체에 validation 관련 어노테이션 선언
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EventDto {
@NotEmpty
private String name;
@NotEmpty
private String description;
@NotNull
private LocalDateTime beginEnrollmentDateTime;
@NotNull
private LocalDateTime closeEnrollmentDateTime;
@NotNull
private LocalDateTime beginEventDateTime;
@NotNull
private LocalDateTime endEventDateTime;
private String location; // (optional) 이게 없으면 온라인 모임
@Min(0)
private int basePrice; // (optional)
@Min(0)
private int maxPrice; // (optional)
@Min(0)
private int limitOfEnrollment;
}
도메인 Validator 만들기
@Component
public class EventValidator {
public void validate(EventDto eventDto, Errors errors) {
if (eventDto.getBasePrice() > eventDto.getMaxPrice() && eventDto.getMaxPrice() > 0) {
errors.reject("wrongPrices", "Values fo prices are wrong");
}
LocalDateTime endEventDateTime = eventDto.getEndEventDateTime();
if (endEventDateTime.isBefore(eventDto.getBeginEventDateTime()) ||
endEventDateTime.isBefore(eventDto.getCloseEnrollmentDateTime()) ||
endEventDateTime.isBefore(eventDto.getBeginEnrollmentDateTime())) {
errors.rejectValue("endEventDateTime", "wrongValue", "endEventDateTime is wrong");
}
// TODO BeginEventDateTime
// TODO CloseEnrollmentDateTime
}
}
validator 활용
@PostMapping
public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto , Errors errors) {
// 1.binding 할 때 에러가 존재 확인
// 에러 확인 후 존재하면 에러 코드를 돌려준다.
if(errors.hasErrors()){
return ResponseEntity.badRequest().build();
}
//2.입력값 검증 , eventValidator 로직 검증
eventValidator.validate(eventDto,errors);
//3.에러 확인 후 존재하면 에러 코드를 돌려준다.
if(errors.hasErrors()){
return ResponseEntity.badRequest().build();
}
/**
* modelmapper를 이용해서 dto의 값을 domain객체에 값 복사 해 준다.
*/
Event event = modelMapper.map(eventDto,Event.class);
Event newEvent = eventRepository.save(event);
URI uri = linkTo(EventContoller.class).slash(newEvent.getId()).toUri();
return ResponseEntity.created(uri).body(event); // ResponseEntity를 사용하여 header 정보 등록
}