💻본 포스팅은 '스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 김영한'님의 강의를 듣고 작성되었습니다.
[FieldError, ObjectError]
[입력 오류에도 데이터가 사라지지 않고 그대로 남겨지게 해보자]
- BindingResult를 사용해서 데이터를 바인딩 할 때 오류에도 제대로 컨트롤러를 호출하게 하는 원리와 방법을 알아보았다.
- 그러나 이런 편의점에도 불구하고 우리는 사용자 입력 오류에 입력한 값 그대로 남아있는 것이 아닌 사라지는 현상을 발견할 수 있었다.
- 이를 해결하고자 입력한 값이 남아있도록 하는 방법을 알아보려 한다.
[컨트롤러]
//V2 = 입력값이 올바르지 않아도 데이터를 그대로 화면에 남길 수 있는 코드드
@PostMapping("/add")
public String addItemV2(@ModelAttribute Item item, BindingResult bindingResult,
RedirectAttributes redirectAttributes) {
if (!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false, null, null, "상품 이름은 필수입니다."));
}
if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
bindingResult.addError(new FieldError("item", "price", item.getPrice(), false, null, null, "가격은 1,000 ~ 1,000,000 까지 허용합니다."));
}
if (item.getQuantity() == null || item.getQuantity() > 10000) {
bindingResult.addError(new FieldError("item", "quantity", item.getQuantity(), false, null, null, "수량은 최대 9,999 까지 허용합니다."));
}
//특정 필드 예외가 아닌 전체 예외
if (item.getPrice() != null && item.getQuantity() != null) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
//실제 데이터가 넘어가지 않아서 얘는 bindingFailure이 필요 없음.
bindingResult.addError(new ObjectError("item", null, null, "가격 * 수량의 합은 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}";
}
[사용자 입력 값 유지(FieldError,ObjectError)]
[FieldError]
- 오류 발생시 사용자 입력 값을 저장하는 기능을 제공한다.
- 예
- 가격에 숫자가 아닌 문자가 입력될 경우 가격은 Integer 타입으로 문자를 따로 보관할 방법이 없다.
- 그래서 오류가 발생할 경우 사용자 입력 값을 보관하는 별도의 방법이 필요하다.
- 이때 별도로 입력값을 보관하게 되면, 보관한 사용자의 입력 값을 검증 오류가 발생했을 때 다시 화면에 출력해주면 된다.
- 이 사용자 입력 오류값을 별도로 보관 역할을 하는 것이 FieldError다.
[FieldError 생성자]
public FieldError(String objectName, String field, String defaultMessage);
public FieldError(String objectName, String field, @Nullable Object rejectedValue,
boolean bindingFailure, @Nullable String[] codes, @Nullable Object[] arguments,
@Nullable String defaultMessage)
- objectName : 오류가 발생한 객체 이름
- field : 오류 필드
- rejectedValue : 사용자가 입력한 값(거절된 값)오류 발생시 사용자 입력 값을 저장하는 필드이다.
- bindingFailure : 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분 값
- codes : 메시지 코드
- arguments : 메시지에서 사용하는 인자
- defaultMessage : 기본 오류 메시지
[ObjectError]
- 이 역시도 FieldError와 유사하게 두 가지의 생성자를 제공한다.
[스프링의 바인딩 오류 처리]
- 타입 오류로 바인딩에 실패 시
- 스프링은 FieldError를 생성
- 생성한 FieldError 내에 사용자가 입력한 값을 넣어둔다.(타입 오류로 바인딩 실패한 값)
- 해당 오류를 BindingResult에 담아서 컨트롤러를 호출한다.
- 위의 과정으로 타입 오류 같은 바인딩 실패시에도 사용자의 오류 메시지를 정상 출력
[타임리프의 사용자 입력 값 유지]
- th:field="*{price}"
- 타임리프의 th:field
- 정상 상황에는 모델 객체의 값을 사용
- 오류가 발생하면 FieldError에서 보관한 값을 사용해서 값을 출력한다
'Back-End > Spring' 카테고리의 다른 글
[Spring MVC2][검증(Validation)] - 컨트롤러와 검증의 분리 (0) | 2022.05.02 |
---|---|
[Spring MVC2][검증(Validation)] - 오류 코드와 메시지 처리 (0) | 2022.04.27 |
[Spring MVC2][검증(Validation)] - BindingResult(부제: 검증 오류 스프링부트와 타임리프가 손쉽게 지원하는 법, 바인딩 오류에도 400오류가 아닌 제대로 컨트롤러를 호출하는 법) (0) | 2022.04.27 |
[Spring MVC2][검증(Validation)] - 직접 검증 (0) | 2022.04.25 |
[Spring MVC2][메시지, 국제화] - 메시지, 국제화 (0) | 2022.04.25 |