Spring Boot中javax.validation.constraints在POST请求中校验失效问题排查
嘿,我帮你找到了几个导致校验规则不生效、自定义InputException无法触发的关键问题,咱们一步步解决:
1. 最核心的问题:BindingResult参数顺序错误
在Spring MVC的控制器方法里,被@Valid标记的参数和BindingResult必须紧挨着,而且BindingResult要放在被校验参数的后面。你现在的方法参数顺序是:
public void save( @Valid @RequestBody Mathematics maths, HttpServletResponse response, BindingResult theBindingResult) throws IOException
这种情况下,Spring没办法把校验错误填充到BindingResult里,而是会直接抛出MethodArgumentNotValidException异常,根本走不到你写的if(theBindingResult.hasErrors())判断逻辑里。
把参数顺序调整成这样就对了:
public void save( @Valid @RequestBody Mathematics maths, BindingResult theBindingResult, HttpServletResponse response) throws IOException
2. 校验注解不匹配你的实际需求
关于question字段
你用了@NotNull,但这个注解只检查字段是否为null——虽然你的StringTrimmerEditor(true)会把全空格的字符串转成null,这时候@NotNull其实能触发,但为了更严谨,建议换成@NotBlank。@NotBlank会同时检查null、空字符串和全空格的情况,完全贴合你"不允许为null或空字符串"的需求:
import javax.validation.constraints.NotBlank; // ... @Column(name = "question") @NotBlank(message = "Question cannot be empty or consist only of spaces") private String question;
关于date字段
你的@Pattern正则是对的,但可以加上message属性让错误信息更清晰,另外要确保导入的是javax.validation.constraints.Pattern(Spring Boot 2.x版本),不要用Hibernate的注解,避免冲突:
import javax.validation.constraints.Pattern; // ... @Column(name = "date") @Pattern(regexp = "(19[0-9]{2})|(20[0-9]{2})", message = "Date must be a 4-digit year starting with 19 or 20") private String date;
3. 小细节:确保依赖正确(你的pom已经满足,但提一下)
你的pom.xml里已经引入了hibernate-validator,Spring Boot 2.5.x版本会自动集成校验功能,这部分没问题,不用额外调整。
修复后的测试
现在你再发送那个POST请求{"questionNo":14, "date":"1890", "question":" "}:
question的" "会被StringTrimmerEditor转为null,触发@NotBlank校验错误;date的"1890"不符合正则,触发@Pattern校验错误;- 因为
BindingResult在正确的位置,这些错误会被收集起来,你的if判断会生效,成功抛出自定义的InputException。
内容的提问来源于stack exchange,提问作者Chinedu

