코드 그라데이션

오류 코드와 메시지 처리 (2) 본문

Spring/Validation

오류 코드와 메시지 처리 (2)

완벽한 장면 2024. 2. 25. 23:00

오류 코드와 메시지 처리 (2)

목표

  • FieldError , ObjectError 는 다루기 너무 번거롭다.
  • 오류 코드도 좀 더 자동화 할 수 있지 않을까? 예) item.itemName 처럼?

컨트롤러에서 BindingResult 는 검증해야 할 객체인 target 바로 다음에 온다. 

따라서 BindingResult 는 이미 본인이 검증해야 할 객체인 target 을 알고 있다.

 

 

로그 코드를 앞선 메서드에 추가해서 결과를 확인해본다.

@PostMapping("/add")
public String addItemV3(@ModelAttribute Item item,
                        BindingResult bindingResult,
                        RedirectAttributes redirectAttributes) {

	// 요기 추가
    log.info("objectName={}", bindingResult.getObjectName());
    log.info("target={}", bindingResult.getTarget());

    if (!StringUtils.hasText(item.getItemName())) {
        bindingResult.addError(new FieldError("item", "itemName",
                item.getItemName(), false, new String[]{"required.item.itemName", "required.default"}, null,
                null));
    }

    if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
        bindingResult.addError(new FieldError("item", "price", item.getPrice(),
                false, new String[]{"range.item.price"}, new Object[]{1000, 1000000},
                null));
    }

    if (item.getQuantity() == null || item.getQuantity() > 10000) {
        bindingResult.addError(new FieldError("item", "quantity",
                item.getQuantity(), false, new String[]{"max.item.quantity"},
                new Object[]{9999}, null));
    }

    // 생략
}

이렇게 알아서 다 들어온다.

 


rejectValue() , reject()

  • BindingResult 가 제공하는 rejectValue() , reject() 를 사용하면 FieldError , ObjectError 를 직접 생성하지 않고,          깔끔하게 검증 오류를 다룰 수 있다.

rejectValue() , reject() 를 사용해서 기존 코드를 단순화해보자.

 

ValidationItemControllerV2 - addItemV4() 추가

@PostMapping("/add")
public String addItemV4(@ModelAttribute Item item,
                        BindingResult bindingResult,
                        RedirectAttributes redirectAttributes) {

    log.info("objectName={}", bindingResult.getObjectName());
    log.info("target={}", bindingResult.getTarget());

    // 에러 검증 코드
    if (!StringUtils.hasText(item.getItemName())) {
        bindingResult.rejectValue("itemName", "required");
    }
    if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
        bindingResult.rejectValue("price", "range", new Object[]{1000, 1000000},
                null);
    }
    if (item.getQuantity() == null || item.getQuantity() > 10000) {
        bindingResult.rejectValue("quantity", "max", new Object[]{9999},
                null);
    }

    //특정 필드 예외가 아닌 전체 예외
    if (item.getPrice() != null && item.getQuantity() != null) {
        int resultPrice = item.getPrice() * item.getQuantity();
        if (resultPrice < 10000) {
            bindingResult.reject("totalPriceMin", new Object[]{10000,
                    resultPrice}, null);
        }
    }
    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}";
}

유의할 점은

  • errorCode 영역에 전체를 다 적지 않고, 맨 앞 단어만 적었다는 것이다.

그런데 실행해도 문제없이 잘 작동한다.

 

 

rejectValue() 들어가보면

- 생성자는 2개

 

  • 앞에서 BindingResult 는 어떤 객체를 대상으로 검증하는지 target을 이미 알고 있다고 했다.                                       따라서 target(item)에 대한 정보는 없어도 된다. 오류 필드명은 동일하게 price 를 사용했다.

 

 

 

errors.properties

range.item.price=가격은 {0} ~ {1} 까지 허용합니다.

reject()

물론 생성자가 3개가 있지만,

위의 내용과 논리가 동일하다.

 

다음 시간에 더 자세히...

728x90

'Spring > Validation' 카테고리의 다른 글

오류 코드와 메시지 처리 (4)  (0) 2024.02.26
오류 코드와 메시지 처리 (3)  (0) 2024.02.25
오류 코드와 메시지 처리 (1)  (0) 2024.02.24
FieldError와 ObjectError  (0) 2024.02.23
BindingResult 두 번째  (0) 2024.02.22
Comments