코드 그라데이션

Validator 분리 (1) 본문

Spring/Validation

Validator 분리 (1)

완벽한 장면 2024. 2. 28. 00:33

Validator 분리 (1)  

목표

  • 복잡한 검증 로직을 별도로 분리하자.

 

컨트롤러에서 검증 로직이 차지하는 부분은 매우 크다. 이런 경우 별도의 클래스로 역할을 분리하는 것이 좋다. 

그리고 이렇게 분리한 검증 로직을 재사용 할 수도 있다.

 

새 클래스 ItemValidator 생성

package hello.itemservice.web.validation;

import hello.itemservice.domain.item.Item;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

@Component
public class ItemValidator implements Validator {

    // 지정된 클래스가 이 유효성 검사기를 지원하는지 확인
    @Override
    public boolean supports(Class<?> clazz) {
        return Item.class.isAssignableFrom(clazz);
    }

    // 주어진 객체의 유효성을 검사
    @Override
    public void validate(Object target, Errors errors) {
        // 주어진 객체를 Item으로 캐스팅
        Item item = (Item) target;

        // 아이템 이름 필드가 비어 있거나 공백 문자로만 이루어져 있으면 "required" 에러 발생
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "itemName", "required");

        // 아이템의 가격이 범위를 벗어나면 "range" 에러 발생
        if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
            errors.rejectValue("price", "range", new Object[]{1000, 1000000}, null);
        }

        // 아이템 수량이 최대 허용값을 초과하면 "max" 에러 발생
        if (item.getQuantity() == null || item.getQuantity() > 10000) {
            errors.rejectValue("quantity", "max", new Object[]{9999}, null);
        }

        // 아이템의 가격과 수량이 모두 존재하는 경우, 두 값을 곱한 결과가 최소값보다 작으면 "totalPriceMin" 에러 발생
        if (item.getPrice() != null && item.getQuantity() != null) {
            int resultPrice = item.getPrice() * item.getQuantity();
            if (resultPrice < 10000) {
                errors.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
            }
        }
    }
}

 

 

 

Validator 인터페이스의 구성


ItemValidator 직접 호출하기

1. 위에 의존성 주입

@Slf4j
@Controller
@RequestMapping("/validation/v2/items")
@RequiredArgsConstructor
public class ValidationItemControllerV2 {

    private final ItemRepository itemRepository;
    private final ItemValidator itemValidator; // 추가
    
    ...
}

 

2. ValidationItemControllerV2 - addItemV5()

    @PostMapping("/add")
    public String addItemV5(@ModelAttribute Item item,
                            BindingResult bindingResult,
                            RedirectAttributes redirectAttributes) {
        // 딱 한줄로 축약 (위에 의존성 주입! private final ItemValidator itemValidator;)
        itemValidator.validate(item, bindingResult);

        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}";
    }

 

실행해보면, 동일한 결과가 호출이 된다!

728x90

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

Bean Validation - 소개  (0) 2024.02.29
Validator 분리 (2)  (0) 2024.02.28
오류 코드와 메시지 처리 (6)  (0) 2024.02.27
오류 코드와 메시지 처리 (5)  (1) 2024.02.27
오류 코드와 메시지 처리 (4)  (0) 2024.02.26
Comments