JSR-303 验证组定义缺省组

2022-09-01 10:34:27

我有一个bean,它有很多用JSR-303验证注释注释的字段。现在有一项新要求,即其中一个字段是必填字段,但仅在特定条件下。

我环顾四周,找到了我需要的东西,验证组。

这就是我现在拥有的:

public interface ValidatedOnCreationOnly {
}

@NotNull(groups = ValidatedOnCreationOnly.class)
private String employerId;
@Length(max = 255)
@NotNull
private String firstName;
@Length(max = 255)
@NotNull
private String lastName;

但是,当我在单元测试中运行此验证时:

@Test
public void testEmployerIdCanOnlyBeSetWhenCreating() {
    EmployeeDTO dto = new EmployeeDTO();

    ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
    Set<ConstraintViolation<EmployeeDTO>> violations = vf.getValidator().validate(dto, EmployeeDTO.ValidatedOnCreationOnly.class);

    assertEquals(violations.size(), 3);
}

事实证明,所有非组注释的验证都被忽略了,我只得到了1个违规。

我可以理解这种行为,但我想知道是否有办法使组也包含所有未注释的参数。如果没有,我必须做这样的事情:

public interface AlwaysValidated {
}

public interface ValidatedOnCreationOnly extends AlwaysValidated {
}

@NotNull(groups = ValidatedOnCreationOnly.class)
private String employerId;
@Length(max = 255, groups = AlwaysValidated.class)
@NotNull(groups = AlwaysValidated.class)
private String firstName;
@Length(max = 255, groups = AlwaysValidated.class)
@NotNull(groups = AlwaysValidated.class)
private String lastName;

我正在使用的实际类有更多的字段(大约20个),所以这种方法将指示验证的明确方式变成了一团糟。

谁能告诉我是否有更好的方法?也许是这样的:

vf.getValidator().validate(dto, EmployeeDTO.ValidatedOnCreationOnly.class, NonGroupSpecific.class);

我正在一个春季项目中使用它,所以如果春天有另一种方式,我会很高兴知道。


答案 1

中有一个组,它表示缺省的 Bean 验证组。除非显式定义了组列表:Defaultjavax.validation.groups.Default

  • 约束属于组Default
  • 验证适用于组Default

您可以扩展此组:

public interface ValidatedOnCreationOnly extends Default {}

答案 2

只是想添加更多:

如果你正在使用弹簧框架,你可以使用org.springframework.validation.Validator

@Autowired
private Validator validator;

并手动执行验证:

validator.validate(myObject, ValidationErrorsToException.getInstance());

和控制器中:

@RequestMapping(method = RequestMethod.POST)
public Callable<ResultObject> post(@RequestBody @Validated(MyObject.CustomGroup.class) MyObject request) {
    // logic
}

尽管以这种方式扩展从不起作用,因此您必须包含在组中:javax.validation.groups.DefaultDefault.class

class MyObject {

    @NotNull(groups = {Default.class, CustomGroup.class})
    private String id;

    public interface CustomGroup extends Default {}
}

推荐