'combining' 两个端点时 javax 验证注释重用的模式

Pattern for javax validation annotation reuse when 'combining' two endpoints

我有一个 API 有两个实体 FooBar 一对多关系,即每个 Bar 必须引用一个 Foo.

我有端点可以创建 FooBar - 这些端点有各自的 DTO,使用 javax 验证定义。

public class CreateFooDto {
  @NotNull public Integer field1;
  @Length(min=1, max=8) public String field2;
}

public class CreateBarDto {
  @NotNull public Boolean field1;
  @NotEmpty public String field2;

  @NotNull public String fooId; // the foreign key to Foo
}

现在,我想要一个新端点,它创建 Bar Foo 并将它们链接在一起,而不是首先创建 Foo 然后创建 Bar 传递 fooId。除了需要 CreateBarDto.fooId 之外,我将需要所有具有相同验证的相同字段。理想情况下,我想重用我已经定义的 javax 验证,而不是重复它们。

我想将现有的 DTO 嵌套在新端点的组合 DTO 中,但是 CreateBarDto.fooId 上的 @NotNull 存在问题 - 实际上 不是 必填。到目前为止,我想出的最好的解决方案是:

public class CreateBarWithFooDto {
  @Valid public CreateFooDto foo;
  @Valid public CreateBarDto bar;
}

public class CreateBarDto {
  @NotNull public Boolean field1;
  @NotEmpty public String field2;

  public String fooId; // the foreign key to Foo
  public boolean fooIdNotRequired; // optional flag to indicate fooId not required

  @AssertTrue
  public boolean isFooIdRequired() {
    return fooIdNotRequired || fooId != null;
  }
}

虽然这行得通,但确实很笨重。只是想知道是否有人可以建议一个更好的模式来重用像这样的 javax 验证,或者是否有任何我不知道的 javax 注释可能有助于解决这个问题?

一种选择是使用验证组。 javax.validation.groups 的 javadoc 说:

A group defines a subset of constraints. Instead of validating all constraints for a given object graph, only a subset is validated depending on the group targeted.

Each constraint declaration defines the list of groups it belongs to. If no group is explicitly declared, a constraint belongs to the Default group.

When applying validation, the list of target groups is passed along. If no group is explicitly passed along, the javax.validation.groups.Default group is used.

因此,在 CreateBarDto 中举个例子,我们可以有一个新组 MyFirstGrup.class field1 和 field2

的验证
public class CreateBarDto {
  @NotNull(groups = {MyFirstGrup.class}) 
  public Boolean field1;
  @NotEmpty(groups = {MyFirstGrup.class})
  public String field2;

  @NotNull public String fooId; // the foreign key to Foo
}

您现在需要触发通常通过

的特定组
validator.validate(yourBean, MyFirstGrup.class);

如果您使用 Spring 检查 @Validated 注释,它支持指定您需要 运行 的组。更多信息 here