BindingResult ?
검증 오류 (HTTP 파라미터 또는 Controller 로직)가 발생할 경우에 해당 오류의 내용을 보관하는 스프링 프레임워크 객체
BindingResult 주의
- BindingResult는 검증할 대상 바로 다음에 와야함.
ex) @ModelAttribute Test test, BindingResult bindingResult- Model에 직접 넣어주는 작업을 하지 않아도 된다.
참고
BindingResult : interface
Errors : interface
Error -> BindingResult 상속
BindingResult - controller
@PostMapping("/add") public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { /** * BindingResult ? * @ModelAttribute 다음에 와야한다. * modelAttribute에 담는 과정은 필요 없음. */ //검증 오류 결과 보관 과정 생략 //Map<String, String> errors = new HashMap<>(); //특정 필드 검증 로직 if(!StringUtils.hasText(item.getItemName())) { bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수 입니다.")); } if(item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) { bindingResult.addError(new FieldError("item", "price", "상품 금액은 1,000원 ~ 1,000,000원 사이 가격을 입력해주세요.")); } if(item.getQuantity() == null || item.getQuantity() >=9999) { bindingResult.addError(new FieldError("item", "quantity", "수량은 9,999개 이하로 입력해주세요.")); } //특정 필드가 아닌 복합 룰 검증 if(item.getPrice() != null && item.getQuantity() != null) { int resultPrice = item.getPrice() * item.getQuantity(); if (resultPrice < 10000) { bindingResult.addError(new ObjectError("item", "가격 X 수량은 10,000원 이상이여야 합니다. (현재입력=" + resultPrice + ")")); } } //검증 조건 미충족시 다시 입력 폼으로 if(bindingResult.hasErrors()) { log.info("errors = {}", bindingResult); return "validation/v2/addForm"; } //성공 로직 Item savedItem = itemRepository.save(item); redirectAttributes.addAttribute("itemId", savedItem.getId()); redirectAttributes.addAttribute("status", true); return "redirect:/validation/v2/items/{itemId}"; }
BindingResult - html
global error
<div th:if="${#fields.hasGlobalErrors()}"> <p class="field-error" th:each="err : ${#fields.globalErrors()}" th:text="${err}">글로벌 오류 메시지 </p> </div>
global error는 방대한 분량을 가지고 있어서 반복해서 출력
field error
<div> <label for="itemName" th:text="#{label.item.itemName}"> 상품명 </label> <input type="text" id="itemName" th:field="*{itemName}" th:errorclass="field-error" class="form-control" placeholder="이름을 입력하세요"> <div class="field-error" th:errors="*{itemName}"> 상품명 오류 </div> </div>
🪴 원리
타임리프는 스프링의 BindingResult를 활용 할 수 있다.
- #fields: #fields로 BindingResult 접근
- th:errors : 해당 필드의 오류가 있는 경우 태그 출력
- th:errorclass: th:field에 지정한 필드에 오류가 있으면 class 출력