Spring Boot Starter Data Rest,@NotNull约束不起作用。

5
我试图在我的Person对象中添加@NotNull约束,但我仍然可以使用null电子邮件@POST新的Person。我正在使用Spring boot rest和MongoDB。
实体类:
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
}

仓库(Repository)类:
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String> {
}

应用程序类:
@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 发布一个新对象时,例如:
{
  "username": "deadpool",
  "email": null
}

我仍然得到状态码 201,并且使用此有效载荷创建:
{
    "username": "deadpool",
    "password": null,
    "email": null
     ....
     ....
}

1
好的,无论你收到什么参数,在对象之前加上@Valid标记。 - dambros
1
@dambros 他的代码库有一个 @RepositoryRestResource 注解,这种情况下你不需要一个控制器。如果你使用它,Spring 将自动为 REST 调用创建一个控制器。 - Jesper
1
@oxyt,这仅适用于基于JPA的实现,因为在通过JPA插入/更新数据之前进行了有效性检查,并且它可以干净地处理。我认为这是Spring Data Hateoas团队在Web层面上的一个很好的功能请求。我认为你应该在他们的github位置打开一个问题,看看是否能得到更多关于这个问题的反馈。 - Biju Kunjummen
1
@oxyt,在这里开了一个 Github 问题 - https://github.com/spring-projects/spring-hateoas/issues/446 - Biju Kunjummen
1
你需要开启验证 - Marc Tarin
显示剩余8条评论
4个回答

7
我有过相同的问题,但仅启用验证并没有对我起作用。以下解决方案可适用于JPA和MongoDb,以免其他人花费大量时间处理此问题。通过此方法不仅可以使验证运行正常,而且我还能获得漂亮的RESTful 400错误,而不是默认的500错误。
必须将以下内容添加到我的build.gradle依赖项中。
    compile('org.hibernate:hibernate-validator:4.2.0.Final')

还有这个配置类

@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());
   }
}

当我添加你的配置时,我一直收到这个错误:java.lang.AbstractMethodError: org.hibernate.validator.engine.ValidatorFactoryImpl.close()V 你有任何解决方法吗?(末尾的V不是打字错误) - Red fx

3

我发现自己制作的@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("");
    }

}

谢谢Sheikh Abdul,我稍后会尝试这个 :) - oxyt

0
通常情况下,@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();
        }
    }
}

0
您可以使用以下代码进行验证。
@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;
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接