Spring 引导启动器数据剩余,@Notnull 约束不起作用
Spring boot starter data rest, @Notnull constraint not working
我正在尝试将 @NotNull 约束添加到我的 Person 对象中,但我仍然可以 @POST 一个带有空电子邮件的新 Person。我正在使用 Spring boot rest 和 MongoDB。
实体class:
import javax.validation.constraints.NotNull;
public class Person {
@Id
private String id;
private String username;
private String password;
@NotNull // <-- Not working
private String email;
// getters & setters
}
存储库class:
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String> {
}
申请class:
@SpringBootApplication
public class TalentPoolApplication {
public static void main(String[] args) {
SpringApplication.run(TalentPoolApplication.class, args);
}
}
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
...
当我通过 Postman @POST 一个新对象时,例如:
{
"username": "deadpool",
"email": null
}
我仍然 STATUS 201
使用此负载创建:
{
"username": "deadpool",
"password": null,
"email": null
....
....
}
我遇到了同样的问题,但仅启用验证对我不起作用,这确实适用于 JPA 和 MongoDb 以节省其他人在这方面花费的时间。这不仅使验证工作正常,而且我得到一个很好的 restful 400 错误而不是默认的 500。
必须将其添加到我的 build.gradle 依赖项中
compile('org.hibernate:hibernate-validator:4.2.0.Final')
和此配置 class
@Configuration
public class CustomRepositoryRestConfigurerAdapter extends RepositoryRestConfigurerAdapter {
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean();
}
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("afterCreate", validator());
validatingListener.addValidator("beforeCreate", validator());
validatingListener.addValidator("afterSave", validator());
validatingListener.addValidator("beforeSave", validator());
}
}
我发现制作我自己的 @NotNull 注释版本更好,它也可以验证空字符串。
@Documented
@Constraint(validatedBy = NotEmptyValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmpty {
String message() default "{validator.notEmpty}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class NotEmptyValidator implements ConstraintValidator<NotEmpty, Object> {
@Override
public void initialize(NotEmpty notEmpty) { }
@Override
public boolean isValid(Object obj, ConstraintValidatorContext cxt) {
return obj != null && !obj.toString().trim().equals("");
}
}
您可以使用以下代码进行验证
@Configuration
@Import(value = MongoAutoConfiguration.class)
public class DatabaseConfiguration extends AbstractMongoConfiguration
{
@Resource
private Mongo mongo;
@Resource
private MongoProperties mongoProperties;
@Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
return new ValidatingMongoEventListener(validator());
}
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
@Override
protected String getDatabaseName() {
return mongoProperties.getDatabase();
}
@Override
public Mongo mongo() throws Exception {
return mongo;
}
}
通常,@RestRepository 将解析为一个控制器,而不是自己处理验证,除非您重写默认行为或通过包含一些 @HandleBeforeSave
、@HandleBeforeCreate
、...到您的代码。
一个解决方案是删除 @HandleBeforeSave
、@HandleBeforeCreate
、...
然后 spring 将再次处理验证。
或者如果你想保留它们,你可以像这样为任何对象验证提供一个处理程序:
@Component
@RepositoryEventHandler
public class EntityRepositoryEventHandler {
@Autowired
private Validator validator;
@HandleBeforeSave
@HandleBeforeCreate
public void validate(Object o) {
Set<ConstraintViolation<Object>> violations = this.validator.validate(o);
if (!violations.isEmpty()) {
ConstraintViolation<Object> violation = violations.iterator().next();
// do whatever your want here as you got a constraint violation !
throw new RuntimeException();
}
}
}
我正在尝试将 @NotNull 约束添加到我的 Person 对象中,但我仍然可以 @POST 一个带有空电子邮件的新 Person。我正在使用 Spring boot rest 和 MongoDB。
实体class:
import javax.validation.constraints.NotNull;
public class Person {
@Id
private String id;
private String username;
private String password;
@NotNull // <-- Not working
private String email;
// getters & setters
}
存储库class:
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String> {
}
申请class:
@SpringBootApplication
public class TalentPoolApplication {
public static void main(String[] args) {
SpringApplication.run(TalentPoolApplication.class, args);
}
}
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
...
当我通过 Postman @POST 一个新对象时,例如:
{
"username": "deadpool",
"email": null
}
我仍然 STATUS 201
使用此负载创建:
{
"username": "deadpool",
"password": null,
"email": null
....
....
}
我遇到了同样的问题,但仅启用验证对我不起作用,这确实适用于 JPA 和 MongoDb 以节省其他人在这方面花费的时间。这不仅使验证工作正常,而且我得到一个很好的 restful 400 错误而不是默认的 500。
必须将其添加到我的 build.gradle 依赖项中
compile('org.hibernate:hibernate-validator:4.2.0.Final')
和此配置 class
@Configuration
public class CustomRepositoryRestConfigurerAdapter extends RepositoryRestConfigurerAdapter {
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean();
}
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("afterCreate", validator());
validatingListener.addValidator("beforeCreate", validator());
validatingListener.addValidator("afterSave", validator());
validatingListener.addValidator("beforeSave", validator());
}
}
我发现制作我自己的 @NotNull 注释版本更好,它也可以验证空字符串。
@Documented
@Constraint(validatedBy = NotEmptyValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmpty {
String message() default "{validator.notEmpty}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class NotEmptyValidator implements ConstraintValidator<NotEmpty, Object> {
@Override
public void initialize(NotEmpty notEmpty) { }
@Override
public boolean isValid(Object obj, ConstraintValidatorContext cxt) {
return obj != null && !obj.toString().trim().equals("");
}
}
您可以使用以下代码进行验证
@Configuration
@Import(value = MongoAutoConfiguration.class)
public class DatabaseConfiguration extends AbstractMongoConfiguration
{
@Resource
private Mongo mongo;
@Resource
private MongoProperties mongoProperties;
@Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
return new ValidatingMongoEventListener(validator());
}
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
@Override
protected String getDatabaseName() {
return mongoProperties.getDatabase();
}
@Override
public Mongo mongo() throws Exception {
return mongo;
}
}
通常,@RestRepository 将解析为一个控制器,而不是自己处理验证,除非您重写默认行为或通过包含一些 @HandleBeforeSave
、@HandleBeforeCreate
、...到您的代码。
一个解决方案是删除 @HandleBeforeSave
、@HandleBeforeCreate
、...
然后 spring 将再次处理验证。
或者如果你想保留它们,你可以像这样为任何对象验证提供一个处理程序:
@Component
@RepositoryEventHandler
public class EntityRepositoryEventHandler {
@Autowired
private Validator validator;
@HandleBeforeSave
@HandleBeforeCreate
public void validate(Object o) {
Set<ConstraintViolation<Object>> violations = this.validator.validate(o);
if (!violations.isEmpty()) {
ConstraintViolation<Object> violation = violations.iterator().next();
// do whatever your want here as you got a constraint violation !
throw new RuntimeException();
}
}
}