Spring Validator中ValidationUtils工具方法工作原理及报错解决
Spring Validator 使用问题咨询
场景代码
@Component("singerValidator") public class SingerValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return Singer.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "firstName", "firstName.empty"); } }
运行错误信息
Exception in thread "main" org.springframework.beans.NotReadablePropertyException: Invalid property 'firstName' of bean class [com.example.spring.tutorial.demo.ch10.validators.SingerValidator]: Bean property 'firstName' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter? at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:627) at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:617) at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:105) at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:225) at org.springframework.validation.ValidationUtils.rejectIfEmpty(ValidationUtils.java:172) at org.springframework.validation.ValidationUtils.rejectIfEmpty(ValidationUtils.java:115) at com.example.spring.tutorial.demo.ch10.validators.SingerValidator.validate(SingerValidator.java:18) at org.springframework.validation.ValidationUtils.invokeValidator(ValidationUtils.java:89) at org.springframework.validation.ValidationUtils.invokeValidator(ValidationUtils.java:56) at com.example.spring.tutorial.demo.ch10.Demo.main(Demo.java:28)
疑问
错误提示SingerValidator类没有firstName属性的getter方法,但该字段实际定义在Singer类中,现咨询:
ValidationUtils.rejectIfEmpty不接收target参数是如何工作的?- 如何修复这段代码?
- 我遗漏了什么?
问题解答
1. ValidationUtils.rejectIfEmpty的工作逻辑
ValidationUtils.rejectIfEmpty无需显式传入target,是因为Errors对象内部已经绑定了待校验的目标实例。当创建Errors实现类(比如BeanPropertyBindingResult)时,必须传入要校验的对象,Errors会持有该对象的引用。调用ValidationUtils的校验方法时,工具类会通过Errors获取到目标对象,再通过反射读取指定字段的值,判断是否为空并触发错误提示。
2. 代码修复方案
报错的核心原因是调用校验时传入的目标对象错误——把SingerValidator实例当成了被校验对象传入,而不是Singer实体类实例。
正确的校验调用示例:
// 1. 创建待校验的Singer实例 Singer singer = new Singer(); // 2. 创建Errors对象,绑定目标实例 Errors errors = new BeanPropertyBindingResult(singer, "singer"); // 3. 获取校验器实例(从Spring容器或直接实例化) SingerValidator validator = context.getBean(SingerValidator.class); // 4. 执行校验:传入正确的target(singer)和errors ValidationUtils.invokeValidator(validator, singer, errors); // 或者直接调用校验器的validate方法 validator.validate(singer, errors);
检查Demo.java第28行,确认invokeValidator的第二个参数是Singer实例,而非SingerValidator本身。
3. 遗漏的核心点
- 混淆了校验器与被校验对象:错误地将校验器自身作为校验目标传入,导致Spring在校验器类中查找
firstName字段,自然无法找到。 - 对
Errors的绑定逻辑不清晰:Errors必须与待校验的实体对象绑定,ValidationUtils的所有校验操作都依赖Errors来获取目标对象的字段值。
内容的提问来源于stack exchange,提问作者totalfrank
相关产品推荐
相关产品推荐

