Spring - Validation - Validator분리 1

현시기얌·2021년 7월 18일
0

Validation

목록 보기
6/8


위와 같이 컨트롤러에서 검증 로직이 차지하는 부분이 매우 크다. 이런 경우네는 별도의 클래스로 역할을 분리하는 것이 좋다.
또한 클래스로 분류하게 되면 재사용성에도 용이해진다.

@Component
public class ItemValidator implements Validator {
	
    @Override 
    public boolean supports(Class<?> clazz) {
    	return Item.class.isAssignableFrom(clazz);
        // item == clazz
        // item == subItem 
    }

해당 클래스가 Item 클래스 인지 아니면 Item의 자식 클래스인지 확인해주는 supprots 메소드
= Validator가 지원하는 Class 인지 확인하는 Method

    @Override
    public void validate(Object targetm Errors errors) {
    	// Object는 item
        // Errors 는 bindingResult 의 부모 클래스

        Item item = (Item) target;
        //검증 로직
        if (!(StringUtils.hasText(item.getItemName()))) {
            errors.rejectValue("itemName", "required");
        }
        
        if (item.getPrice() == null || item.getPrice() < 100 || 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);
            }
        }
    }

검증 하는 Method에는 컨트롤러에서 구현했던 검증 로직을 그대로 쓰면 된다.
이때 Errors는 bindingResult의 부모 클래스 이므로
bindingResult.rejectValue() -> errors.rejectValue()로 바꿔도 괜찮다.

@Controller
@RequiredArgsConstructor
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) {

	//Validator로 검증
        itemValidator.validate(item, bindingResult);


        // 검증에 실패하면 다시 입력 폼으로
        if (bindingResult.hasErrors()) {
            log.info("bindingResult = {}", 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}";
    }

컨트롤러에서는 Validator를 스프링 Bean으로 주입 받아서 직접 호출하기만 하면 기존과 동일하게 작동한다.

참고 : 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술

profile
현시깁니다

0개의 댓글

Powered by GraphCDN, the GraphQL CDN