본문 바로가기
Back/Spring Boot

[SpringBoot] @Valid 어노테이션으로 collection 객체 검증

by 은z 2023. 1. 30.

문제상황

Controller에서 @RequestBody에 @Valid를 사용 할 경우,

단일 Object 타입일 때는 Validator가 잘 동작하지만,

객체가 Collection 타입으로 감싸져 있을 경우에는 Validator가 동작을 하지 못했다.(예외를 내뱉지 않음)

 

아래는 문제가 되는 예시

@PostMapping("")
    public Result doOrder(@RequestBody @Valid List<OrderRequest> order, Errors errors)  {
    
        return orderService.doOrder(order);
    }

 

문제원인

에러가 나지 않는 이유는 @Valid는 JavaBeans에 적용되는데, List(컬렉션)는 JavaBeans 명세에 포함되지 않기 때문이다.

 

해결

Validation.buildDefaultValidatorFactory().getValidator()와 SpringValidatorAdapter를 이용하면 된다.

 

1. CustomValidator 를 만든다.

package com.kiosk.coffee.custom;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;

import javax.validation.Validation;
import java.util.Collection;

// Collection도 Validation 체크 가능하도록 Bean으로 등록
@Component
public class CustomCollectionValidator implements Validator {
    private SpringValidatorAdapter validator;

    public CustomCollectionValidator() {
        this.validator = new SpringValidatorAdapter(
                Validation.buildDefaultValidatorFactory().getValidator()
        );
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true; // 모든 타입 true로 반환
    }

    @Override
    public void validate(Object target, Errors errors) {
        if(target instanceof Collection){
            Collection collection = (Collection) target;

            for (Object object : collection) {
                validator.validate(object, errors);
            }
        } else {
            validator.validate(target, errors);
        }

    }
}

 

2. controller에 생성자 주입 해주고, Dto가 컬렉션일 경우엔 validate(dto, errors) 메소드를 태워준다.

@Autowired
CustomCollectionValidator customCollectionValidator;

@PostMapping("")
public Result doOrder(@RequestBody @Valid List<OrderRequest> order, @ApiIgnore Errors errors)  {
    
    // 이거 추가 : 컬렉션 객체도 검증하도록! 
    customCollectionValidator.validate(order, errors);
    
    return orderService.doOrder(order);
}

 

 

✏️✏️이제 @RequestBody로 받는 컬렉션 내부의 모든 객체들에 대해서 유효성 검사를 하게된다.

 

 

댓글