사실 대부분의 경우가 (예를 들어 회원가입 시) 우리가 만든 User 객체등과 맞지 않다.
예를 들어 회원가입 시에는 기본 User에 대한 정보 뿐 아니라 수많은 약관등의 정보를 가지고 온다.
그래서 컨트롤러에서 User로 받기 보다는 따로 Form전용 객체를 만들고, 거기서 User를 만들어 필요에 맞게 쓴다.
groups 기능은 실무에서 잘 사용하지 않는다.
보통 등록과 수정은 다른 객체로 만든다.
그래서 검증도 중복이 되질 않는다.
@Data
public class ItemSaveForm {
@NotBlank
private String itemName;
@NotNull
@Range(min=1000,max=100000)
private Integer price;
@NotNull
@Max(value = 9999)
private Integer quantity;
public Item getItem(){
return new Item(this.itemName, this.price, this.quantity);
}
}
@Data
public class ItemUpdateForm {
@NotNull
private Long id;
@NotBlank
private String itemName;
@NotNull
@Range(min=1000,max=100000)
private Integer price;
private Integer quantity;
public Item getItem(){
return new Item(this.itemName, this.price, this.quantity);
}
}
음... 뭔가 비슷한게 많다. @애노테이션 만약 이거 인터페이스로 만들어도 재정의 할 수 있을지는..
여튼 이렇게 따로 구분해서 만드니 검증을 다르게 할 수 있다.
@PostMapping("/add")
public String addItem(@Validated @ModelAttribute("item") ItemSaveForm itemForm, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
//검증 오류 보관
validMultiplePrice(itemForm, bindingResult);
if(bindingResult.hasErrors()){
log.info("errors = {}", bindingResult);
return "/validation/v4/addForm";
}
Item item = itemForm.getItem();
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v4/items/{itemId}";
}
private void validMultiplePrice(ItemSaveForm itemForm, BindingResult bindingResult){
if(itemForm.getPrice() != null && itemForm.getQuantity() != null){
int resultPrice = itemForm.getPrice() * itemForm.getQuantity();
if( resultPrice < 10000){
bindingResult.reject("MinQuantityPrice", new Object[]{10000, resultPrice}, null);
}
}
}
private void validMultiplePrice(ItemUpdateForm 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 @ModelAttribute("item") ItemUpdateForm itemForm, BindingResult bindingResult) {
validMultiplePrice(itemForm, bindingResult);
if(bindingResult.hasErrors()){
return "/validation/v4/editForm";
}
Item item = itemForm.getItem();
itemRepository.update(itemId, item);
return "redirect:/validation/v4/items/{itemId}";
}
대충 복합검증 만들어 준 것은 오버로딩 해주긴 했는데.. 어차피 Item 생성을 하니 오버로딩 필요 없었을지도..
여튼 이렇게 따로 구분 해 놓으면 관리하기가 정말 편하다.
@ModelAttribute("item") 이거는 넘어온 정보를 기존 템플릿에 맞게 사용하기 위해 원래 Item이 쓰던 이름으로 넘겼다.
'스프링 > 4. 스프링 MVC-2' 카테고리의 다른 글
43. 도메인과 표현 분리 (0) | 2023.09.04 |
---|---|
42. Http 메시지(Rest API) 검증 (0) | 2023.09.04 |
40. 컨트롤러 간 검증이 다른 경우. (0) | 2023.09.03 |
39. 빈 검증 오브젝트 에러 (0) | 2023.09.03 |
38. 빈 검증기 오류메시지 바꾸기 (0) | 2023.09.03 |