본문 바로가기
Spring/MVC

Validator

by o3oppp 2024. 6. 28.
Validator
public interface Validator {
     boolean supports(Class<?> clazz);
     void validate(Object target, Errors errors);
}
  • Spring이 체계적으로 검증 기능을 도입하기 위해 해당 인터페이스 제공
  • supports() : 해당 검증기를 지원하는 여부 확인
  • validate(Object target, Errors errors) : 검증 대상 객체와 BindingResult를 넘겨서 검증을 수행하고 오류가 있으면 담음
  • Errors는 BindingResult의 상위 인터페이스

1. 직접 호출

  • 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)target;

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

        // 특정 필드가 아닌 복합 룰 검증
        if(item.getPrice() != null && item.getQuantity() != null){
            int resultPrice = item.getPrice() * item.getQuantity();
            if(resultPrice < 10000){
                errors.reject("totalPriceMin", new Object[]{10000,resultPrice},null);
            }
        }
    }
}
  • Controller
public class ValidationItemControllerV2 {

    private final ItemRepository itemRepository;
    private final ItemValidator itemValidator;
    
    @PostMapping("/add")
    public String addItemV5(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {

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

2. WebDataBinder를 통해서 사용

  • Controller
    • @Validated : 검증기를 실행하라는 애노테이션
    • 해당 애노테이션이 붙으면 WebDataBinder에 등록한 검증기를 찾아서 실행
    • 여러 검증기 등록 시 supports()를 통해 어떤 검증기가 실행되어야 하는지 구분
public class ValidationItemControllerV2 {

    private final ItemRepository itemRepository;
    private final ItemValidator itemValidator;
    
    @InitBinder
    public void init(WebDataBinder dataBinder){
    	// WebDataBinder에 검증기를 추가하면 해당 컨트롤러에서는 검증기가 자동으로 적용
        dataBinder.addValidators(itemValidator);
    }
    
    @PostMapping("/add")
    public String addItemV6(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {

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

 

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

서블릿 필터  (0) 2024.07.11
Bean Validation  (0) 2024.06.29
BindingResult  (0) 2024.06.27
Model과 @ModelAttribute  (0) 2024.06.08
@Controller와 @RestController  (1) 2024.06.06