是否可以使用针对@Valid的JSR 303/380规范替换,扩充或拦截Java bean级联验证。基本上,我想使用@Valid批注为每个级联验证执行一些其他处理。
最佳答案
确保您想要它。
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()
, "bean validation fail");
errors.getFieldErrors().add(error);
}
}
}
}
}
}
注册bean
@ControllerAdvice
public class WebDataBindHandler {
@Inject
private LocalValidatorFactoryBean localValidatorFactoryBean;
@InitBinder
void initBinder(WebDataBinder binder) {
binder.addValidators(new JSR303CollectionListValidator(localValidatorFactoryBean));
}
}