使用ConstraintValidator时无法修改字段值是何原因
问题核心原因
你从根上用错了组件:Bean Validation 体系下的ConstraintValidator设计目标是校验字段值是否合法,从来不是用来修改字段值的。不管是JSR380规范本身,还是Spring对Validator的集成实现,都不会把校验过程中你对参数值的修改回写到实体对象字段上,自然不可能实现自动trim的效果。
你代码里的具体错误
initialize方法参数类型完全写错:你实现的校验器绑定的注解是MyConstraint,方法入参却写了IsLessThan,正常情况下应用启动就会抛出类型不匹配异常。就算代码侥幸没报错,你在这里执行trim()操作的对象是注解上配置的field属性值——也就是你写在注解里的"name"字符串本身,这个字符串本来就没有空格,完全碰不到前端传进来的实际字段值,属于操作对象完全错了。isValid方法逻辑完全偏离目标:当你把校验器标在String类型的name字段上时,isValid方法的入参value就是name字段的实际值。你反而在方法里new了BeanWrapperImpl包装这个String值,试图从String对象上获取名为name的属性,除了抛异常或者拿null之外得不到任何有效结果。- 代码里的
@Autowired private String aDependency;是抄示例没删干净的冗余代码,Spring上下文里不存在String类型的可注入Bean,正常启动就会报依赖注入失败的错误,没有任何实际作用。 - 你在
isValid里直接返回true,本质上这个校验器除了走一遍无效逻辑之外,没有做任何和值修改相关的操作,自然不可能改变实体里的字段值。
正确实现String自动trim的方案
不要在校验阶段做值修改,把trim逻辑放在Spring参数绑定/反序列化阶段,这是框架设计预留的值修改扩展点:
全局自动trim(推荐)
自定义Jackson反序列化器,所有接口接收的String类型参数在反序列化时自动去掉前后空格,不需要在每个字段上加注解:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import java.io.IOException; @Configuration public class TrimConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer stringTrimCustomizer() { return builder -> builder.deserializerByType(String.class, new StdScalarDeserializer<>(String.class) { @Override public String deserialize(JsonParser parser, DeserializationContext context) throws IOException { return StringUtils.trimWhitespace(parser.getValueAsString()); } }); } }
指定字段trim
如果只需要给特定字段加trim能力,不要用ConstraintValidator,两种实现方式可选:
- 自定义AOP切面,拦截Controller方法入参,反射扫描带自定义
@AutoTrim注解的String字段,把trim后的值回写到字段上 - 给对应字段配置JPA属性转换器或者Spring MVC属性编辑器,在参数绑定阶段完成值处理
注意:虽然Hibernate Validator有非公开的扩展点支持在校验阶段修改字段值,但这种写法违反Bean Validation规范,框架版本升级很容易失效,生产环境不要用。
内容的提问来源于stack exchange,提问作者user19254373
相关产品推荐
相关产品推荐

