我注意到在@Component声明带有注解的自定义Validator bean时,Spring会完全忽略JSR-303验证。有趣的是,所述自定义验证器甚至不必由任何类填充或使用。Spring扫描其组件的事实似乎足以使Spring在对象绑定期间完全跳过JSR-303验证。@Component从定制Validator中删除并重新启动Web应用程序将按预期启用JSR-303验证。注释自定义验证器@Component有其用途,例如具有Spring Autowire依赖项。
@Component
考虑下面的简单示例:
/* Simple JSR-303 annotated User object */ public class User { @NotNull @Size(min = 2, max = 5) protected String username; @Size(min = 2, max = 32) protected String firstName; @Size(min = 2, max = 32) protected String lastName; @NotNull @Past @DateTimeFormat(pattern="dd/MM/yyyy") protected Date dateOfBirth; @NotNull @Email protected String email; protected String phone; //getters and setters } /* Controller example */ @RestController public class UserController { @PostMapping("/users/register") public ResponseEntity postUser(@Valid @RequestBody User user, BindingResult result) { if (result.hasErrors()) { return new ResponseEntity(result.getAllErrors(), HttpStatus.INTERNAL_SERVER_ERROR); } return new ResponseEntity(user, HttpStatus.CREATED); } } /* Custom validator (doesn't even have to be in use) */ @Component //commenting out @Component annotation enables JSR-303 again public class SomeValidator implements Validator { @Override public boolean supports(Class<?> clazz) { //just an example return false; } @Override public void validate(Object target, Errors errors) { //empty } }
我为这个问题and之以鼻,无法弄清楚为什么我的JSR-303对象没有得到验证,但是我设法缩小了范围,并使用包含上述类的Spring Boot项目来复制它。这是为什么?我在这里缺少什么还是这是Spring的错误?
在GitHub上查看演示Spring Boot项目
因此,您的代码中存在许多问题。首先,您的自定义验证程序不支持任何功能,因此永远不会被调用。您可能意识到了,所以我将由您自己解决。
但是,您真正的问题是,通过创建像这样的验证器bean,Spring既不会创建该defaultValidatorbean(是LocalValidatorFactoryBean),也不会创建该methodValidationPostProcessorbean(用于验证方法参数)。这是人们在Spring中遇到的一个常见问题:一旦您做一些事情来干扰自动配置过程,就必须手动定义。解决方案很简单:创建一个定义这些bean的配置类。例:
defaultValidator
LocalValidatorFactoryBean
methodValidationPostProcessor
@Configuration public class ValidationConfig { @Bean public LocalValidatorFactoryBean defaultValidator() { return new LocalValidatorFactoryBean(); } @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } }