Spring引导启动数据休息,@ Notnull约束不起作用

时间:2016-04-15 14:03:36

标签: json spring mongodb rest spring-data-rest

我正在尝试将@NotNull约束添加到我的Person对象中,但我仍然可以@POST一个带有空电子邮件的新Person。我正在使用MongoDB的Spring启动休息。

实体类:

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
}

存储库类:

@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 @POST新对象时:

{
  "username": "deadpool",
  "email": null
}

我仍然使用此有效负载创建STATUS 201

{
    "username": "deadpool",
    "password": null,
    "email": null
     ....
     ....
}

4 个答案:

答案 0 :(得分:6)

我遇到了同样的问题,但只是启用验证对我来说不起作用,这确实适用于JPA和MongoDb,以节省其他人在这方面的花费时间。这不仅可以使验证工作,而且我得到一个很好的宁静的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());
   }
}

答案 1 :(得分: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("");
    }

}

答案 2 :(得分:0)

您可以使用以下代码进行验证

(function (global) {
System.config({
warnings: true,
paths: {
    // paths serve as alias
    'npm:': 'node_modules/'
},

// map tells the System loader where to look for things
map: {
    'application': 'application', // 'dist',
    'moment': 'node_modules/moment/moment.js',
    'ng-block-ui': 'node_modules/ng-block-ui/bundles/umd',
    'angular2-notifications': 'node_modules/angular2-notifications',
    // angular bundles
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/animations/browser': 'node_modules/@angular/animations/bundles/animations-browser.umd.js',
    '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',   
    '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',

    // angular testing umd bundles
    '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
    '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
    // other libraries
    'rxjs': 'npm:rxjs',
    'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',

},


// packages tells the System loader how to load when no filename and/or no extension
packages: {
    'application': { main: 'main.js', defaultExtension: 'js' },
    'rxjs': {
        defaultExtension: 'js'
    },
    'angular2-in-memory-web-api': {
        defaultExtension: 'js'
    },
    'moment': 'node_modules/moment/moment.js',
        'ng-block-ui': {
        main: 'index.js',
            defaultExtension: 'js'
    }
}

});})(this);

答案 3 :(得分: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();
        }
    }
}