SpringBoot를 쓰면 RequestBody나 ModelAttribute로 Json을 객체에 그대로 바인딩하면서 유효성 체크까지 할 수 있다.
이때 기본적인 Validator는 Collection 형태의 객체는 유효성을 체크하지 않는데 이걸 해주게끔 Validator를 구현했다.
import org.springframework.beans.BeanUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
public class JSR303CollectionListValidator implements Validator {
private final Validator validator;
public JSR303CollectionListValidator(LocalValidatorFactoryBean localValidatorFactoryBean) {
this.validator = localValidatorFactoryBean;
}
@Override
public boolean supports(Class clazz) {
return clazz.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.invokeValidator(validator, target, errors);
if(!target.getClass().isPrimitive()){
PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(target.getClass());
for(PropertyDescriptor descriptor : propertyDescriptors){
if(List.class.isAssignableFrom(descriptor.getPropertyType())){
Method method = descriptor.getReadMethod();
try {
Object object = method.invoke(target);
if(!Objects.isNull(object)){
List typeOfObject = (List) object;
for(Object resource : typeOfObject){
validate(resource, errors);
}
}
} catch (IllegalAccessException | InvocationTargetException e) {
FieldError error = new FieldError(target.getClass().getSimpleName(), descriptor.getName()
, "List 형태의 하위 정보에 대한 validation에 실패하였습니다");
errors.getFieldErrors().add(error);
}
}
}
}
}
}
Spring에서 간단히 DataBind에 등록만 해주면 된다.
@ControllerAdvice
public class WebDataBindHandler {
@Inject
private LocalValidatorFactoryBean localValidatorFactoryBean;
@InitBinder
void initBinder(WebDataBinder binder) {
binder.addValidators(new JSR303CollectionListValidator(localValidatorFactoryBean));
}
}
댓글 없음:
댓글 쓰기