우리는 앞서
public class Item {
private Long id;
@NotBlank
private String itemName;
@NotNull
@Range(min=1000,max=100000)
private Integer price;
@NotNull
@Max(9999)
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
이렇게 애노테이션으로 검증을 손쉽게 적용 했다.
하지만 문제의 요지가 있을 수 있는 점은,
id는 중복을 피하기 위해 서버에서 지정해 주는 것이고, 클라이언트도 입력할 필요가 없다.
만약 수정 시에 id가 NotNull이어야 한다면? (http 메시지를 바꿔서 보내는 것은 너무 쉽다.)
물론 id에 @NotNull 붙이면 되는거 아니야? 라고 생각할 수도 있지만,
그렇게 된다면 우리는 처음 상품을 등록할 때 id를 넣지 않으므로 상품 등록할 때는 필연적으로 상품등록이 거부당한다.
이럴 땐 빈 검증의 그룹 기능을 쓰면 된다.
먼저, 오로지 분리용도로 쓰기 위한 인터페이스를 만든다.
SaveCheck과 UpdateCheck이라는 비어있는 인터페이스를 만든다.
그 후
public class Item {
@NotNull(groups = UpdateCheck.class)
private Long id;
@NotBlank(groups={SaveCheck.class, UpdateCheck.class})
private String itemName;
@NotNull(groups = {UpdateCheck.class, SaveCheck.class})
@Range(min=1000,max=100000)
private Integer price;
@NotNull(groups = {UpdateCheck.class,SaveCheck.class})
@Max(value = 9999, groups = {SaveCheck.class})
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
이건 어떤 그룹에 포함되요, 이런 식으로 알려주면 된다.
@PostMapping("/add")
public String addItem(@Validated(value = SaveCheck.class) @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
//검증 오류 보관
validMultiplePrice(item, bindingResult);
if(bindingResult.hasErrors()){
log.info("errors = {}", bindingResult);
return "/validation/v3/addForm";
}
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v3/items/{itemId}";
}
private void validMultiplePrice(Item item, BindingResult bindingResult){
if(item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if( resultPrice < 10000){
bindingResult.reject("MinQuantityPrice", new Object[]{10000, resultPrice}, null);
}
}
}
@PostMapping("/{itemId}/edit")
public String edit(@PathVariable Long itemId, @Validated(UpdateCheck.class) @ModelAttribute Item item, BindingResult bindingResult) {
validMultiplePrice(item, bindingResult);
if(bindingResult.hasErrors()){
return "/validation/v3/editForm";
}
itemRepository.update(itemId, item);
return "redirect:/validation/v3/items/{itemId}";
}
Validate 안에 이건 어떤 그룹의 검증을 쓸건지 명시한다.
value = 그룹클래스 이렇게 쓰는데,
value = <- 이거는 생략해도 된다. 넣어야 할 속성이 하나만 있으면.
이렇게 하면,
Item에서 지정한 그룹만 검증을 사용한다.
참고로 @Valid는 이런 그룹 기능이 없다.
'스프링 > 4. 스프링 MVC-2' 카테고리의 다른 글
42. Http 메시지(Rest API) 검증 (0) | 2023.09.04 |
---|---|
41. Form 전송객체 분리 (0) | 2023.09.04 |
39. 빈 검증 오브젝트 에러 (0) | 2023.09.03 |
38. 빈 검증기 오류메시지 바꾸기 (0) | 2023.09.03 |
37. 빈 검증 (0) | 2023.09.02 |