代码之家  ›  专栏  ›  技术社区  ›  fps

通过“混合”验证

  •  1
  • fps  · 技术社区  · 6 年前

    我正在springboot2+中开发一个restfulapi,为此我需要执行几个验证。没什么特别的,只是典型的 @NotNull @NotEmpty , @Max @Min , @Email , @Regex , @Future

    除了我有一个API中的bean 必须使用但不能修改

    如果我能创造 混合状 类或接口具有我必须在API中使用的真正dto的相同结构,我很乐意将bean验证的注释放在这些类或接口上。

    例如,如果我有以下无法修改的DTO:

    public class Person {
        private String name;
        private String dateOfBirth;
        private Address address;
    
        // constructors, getters and setters ommited
    }
    
    public class Address {
        private String street;
        private String number;
        private String zipCode;
    
        // constructors, getters and setters ommited
    }
    

    我将创建以下两个接口,模拟它们的结构,并根据需要对它们进行注释:

    public interface PersonMixin {
        @NotBlank String name();
        @Past String dateOfBirth();
        @Valid @NotNull Address address();
    }
    
    public interface AddressMixin {
        @NotBlank String street();
        @Positive int number();
        @NotBlank String zipCode(); // Or maybe a custom validator
    }
    

    如您所见,接口中方法的名称与bean类的属性名称匹配。这只是一个可能的惯例。。。

    然后,理想情况下,在应用程序加载时的某个地方(通常是一些 @Configuration

    ValidationMixinsSetup.addMixinFor(Person.class, PersonMixin.class);
    ValidationMixinsSetup.addMixinFor(Address.class, AddressMixin.class);
    

    除了那个 ValidationMixinsSetup.addMixinFor 是纯粹的幻想,也就是说,它不存在。

    我知道 there exists a similar construct for Jackson 关于JSON序列化/反序列化。我发现它非常有用很多次。

    ValidatorFactory , LocalValidatorFactoryBean , TraversableResolver


    编辑1: 也许这种方法不是最好的。如果你认为有更好的方法,请告诉我。


    编辑2: 这个方法太复杂,太复杂, 鲁布·戈德伯格 等等,我欣赏并尊重这些观点,但我不是在问通过mixin进行验证是好是坏,方便还是不方便,也不是为什么会这样。通过mixins进行验证有其自身的优点,我认为对于一些有效的用例来说,它可能是一种很好的方法,即使用声明式验证而不是脚本式或编程式验证,同时还将验证与模型分离,让底层框架在我只指定约束的情况下执行实际的验证工作,等等。

    1 回复  |  直到 6 年前
        1
  •  3
  •   mark_o    6 年前

    使用 programmatic API (如注释中所述)对于个人,您可以为您的约束应用下一个映射:

        HibernateValidatorConfiguration config = Validation.byProvider( HibernateValidator.class ).configure();
        ConstraintMapping mapping = config.createConstraintMapping();
        mapping.type( Person.class )
                .field( "name" )
                    .constraint( new NotNullDef() )
                .field( "number" )
                    .constraint( new PositiveDef() )
                .field( "address" )
                    .constraint( new NotNullDef() )
                    .valid();
    
        Validator validator = config.addMapping( mapping )
                .buildValidatorFactory()
                .getValidator();