当自定义验证程序带有@Component注释时,将忽略 JSR-303 验证



我注意到JSR-303验证在Spring中被完全忽略了,当声明了一个用@Component注释的自定义验证器bean时。有趣的是,所述自定义验证器甚至不必由任何类填写或使用。Spring扫描的组件似乎足以使Spring在对象绑定期间完全跳过JSR-303验证。从自定义验证程序中删除@Component并重新启动 Web 应用程序将按预期启用 JSR-303 验证。用@Component注释自定义验证器有其用途,例如具有Spring Autowire依赖项。

考虑下面的简单示例:

/* 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
}
}

我对此感到挠头,无法弄清楚为什么我的 JSR-303 对象没有经过验证,但我设法缩小了范围并使用包含上述类的 Spring Boot 项目复制了它。 为什么?我在这里错过了什么还是这是一个春天的错误?

<小时 />

编辑

在 GitHub 上查看演示 Spring Boot 项目

因此,您的代码中存在许多问题。首先,您的自定义验证器不支持任何内容,因此永远不会被调用。你可能意识到了这一点,所以我会把它留给你来修复它。

但是,您真正的问题是,通过创建这样的验证器bean,Spring不会创建defaultValidatorbean(这是一个LocalValidatorFactoryBean),也不会创建methodValidationPostProcessorbean(验证方法参数需要)。这是人们在使用 Spring 时遇到的一个常见问题:一旦你做了一些干扰自动配置过程的事情,你必须手动定义东西。解决方案很简单:创建一个定义这些 bean 的配置类。例:

@Configuration
public class ValidationConfig {
@Bean public LocalValidatorFactoryBean defaultValidator() {
return new LocalValidatorFactoryBean();
}
@Bean public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}

最新更新