在验证 DTO 和实体时,如何避免 Jakarta 验证注释重复?

How to avoid Jakarta validation annotations duplication when validating DTOs and Entities?

提问人:Ruslan K. 提问时间:9/22/2023 最后编辑:Ruslan K. 更新时间:9/22/2023 访问量:72

问:

我正在尝试验证 DTO(传递到控制器方法)和 JPA 实体。但这通常会导致验证规则重复。

应用的验证规则通常与实体类和 DTO 类相似,例如(简化类):

产品实体类的名称带有 @NotEmpty 注释:

@Entity
@Table
class Product {
    @NotEmpty
    private String name;

    // id, getters, setters and so on
}

NewProductRequest DTO 类也有@NotEmpty名称:

class NewProductRequest {
    @NotEmpty
    public String name;
}

在更复杂的方案中,这会导致大量验证重复。 使用此方法时,应用于 Product 的任何验证更改也必须应用于 NewProductRequest。

有没有办法避免验证注释重复,以便遵循 DRY 原则?可以使用 Spring MVC 自定义验证器来实现吗?

java 验证 spring-mvc

评论

1赞 Chaosfire 9/22/2023
您可以通过使用接口抽象出需要验证的数据并写入接口来避免重复。我在这里的答案显示了如何做到这一点。ConstraintValidator

答:

2赞 Ruslan K. 9/22/2023 #1

我真正需要的是注释接口的 getter。

正如 Chaosfire 所指出的,人们可以通过抽象出需要使用接口验证的数据并为接口编写数据来摆脱重复。ConstraintValidator

这里列出了对基类的 getter 进行注释的优点。

对我来说,一个解决方案是注释接口的 getter(我们将其命名为 ValidProduct):

public interface ValidProduct {
    @NotEmpty
    String getName();
}

然后,DTO 和实体类实现此接口。 产品实体类:

@Entity
@Table
public class Product implements ValidProduct {
    private String name;
    
    @Override
    public String getName() {
        return name;
    }
}

NewProductRequest DTO 类如下所示:

public class NewProductRequest implements ValidProduct {
    private String name;

    @Override
    public String getName() {
        return name;
    }
}

然后,这可以与JSR或Spring实现相结合。ConstraintValidatorValidator