@Data
public class Item {
private Long id;
@NotBlank
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
@NotNull
@Max(9999)
private Integer quantity;
NotBlank 라는 오류 코드를 기반으로 MessageCodesResolver
를 통해 다양한 메시지 코드가 순서대로생성된다.
@NotBlank
@Range
errors.properties
# Bean Validation 추가
NotBlank={0} 공백X
Range={0}, {2} ~ {1} 허용
Max={0}, 최대{1}
@NotBlank(message = "공백! {0}")
글로벌 오류 추가
if (item.getPrice() != null && item.getQuantity() != null) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
}
동일한 모델 객체를 등록할 때와 수정할 때 각각 다르게 검증하는 방법을 알아보자
groups
기능을 사용한다.public class Item {
@NotNull(groups = UpdateCheck.class)
private Long id;
@NotBlank(groups = {SaveCheck.class, UpdateCheck.class})
private String itemName;
@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
@Range(min = 1000, max = 1000000, groups = {SaveCheck.class, UpdateCheck.class})
private Integer price;
@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
@Max(value = 9999, groups = {SaveCheck.class})
private Integer quantity;
@Validated(SaveCheck.class)
@Validated(UpdateCheck.class)
참고: @Valid
에는 groups
를 적용할 수 있는 기능이 없다. 따라서 groups
를 사용하려면 @Validated
를 사용해야 한다.
사실 groups
기능은 실제 잘 사용되지는 않는데, 그 이유는 실무에서는 주로 다음에 등장하는 등록용 폼 객체와 수정용 폼 객체를 분리해서 사용하기 때문이다
수정의 경우 등록과 수정은 완전히 다른 데이터가 넘어온다. 생각해보면 회원 가입시 다루는 데이터와 수정시 다루는 데이터는 범위에 차이가 있다. 예를 들면 등록시에는 로그인id, 주민번호 등등을 받을 수 있지만, 수정시에는 이런 부분이 빠진다. 그리고 검증 로직도 많이 달라진다. 그래서
@Valid
, @Validated
는 HttpMessageConverter
(@RequestBody
)에도 적용할 수 있다
@PostMapping("/add")
public Object addItem(
@RequestBody @Validated ItemSaveForm form,
BindingResult bindingResult
)
@ModelAttribute
는 HTTP 요청 파라미터(URL 쿼리 스트링, POST Form)를 다룰 때 사용한다.@RequestBody
는 HTTP Body의 데이터를 객체로 변환할 때 사용한다. 주로 API JSON 요청을 다룰 때 사용한다.@ModelAttribute
는 각각의 필드 단위로 세밀하게 적용된다.
HttpMessageConverter
는 @ModelAttribute
와 다르게 각각의 필드 단위로 적용되는 것이 아니라, 전체 객체 단위로 적용된다.
@ModelAttribute
는 필드 단위로 정교하게 바인딩이 적용된다. 특정 필드가 바인딩 되지 않아도 나머지 필드는 정상 바인딩 되고, Validator를 사용한 검증도 적용할 수 있다.@RequestBody
는 HttpMessageConverter
단계에서 JSON 데이터를 객체로 변경하지 못하면 이후 단계 자체가 진행되지 않고 예외가 발생한다. 컨트롤러도 호출되지 않고, Validator
도 적용할 수 없다.