私有方法上的 Javax 验证不会被触发

Javax validation on private method does not get triggered

假设我有一个非常简单的 Book 模型,我想验证它的标题不是空白。

public class Book {
    @NotBlank
    public String title;
}

在服务层,我像这样执行验证(使用 Hibernate 验证器 quarkus-hibernate-validator):

public class BookService {
    public void validateBook(@Valid Book book) {
        // your business logic here
    }
}

我的资源是:

@Path("/books")
public class BookResource {
    @Inject
    BookService bookService;

    @Path("/service-method-validation")
    @POST
    public String tryServiceMethodValidation(Book book) {
        try {
            bookService.validateBook(book);
            return "Book is valid! It was validated by service method validation.";
        } catch (ConstraintViolationException e) {
            return "Book invalid";
        }
    }

    @Path("/private-method-validation")
    @POST
    public String tryMethodValidation(MessedTitleBook book) {
        try {
            Book book = translate_title(book);
            method(book);
            return "Book is valid! It was validated by method validation.";
        } catch (ConstraintViolationException e) {
            return "Book invalid";
        }
    }

    private void method(@Valid Book book) {
        // your method logic here
    }
}

当我在 /service-method-validation 上 post 一个 Book 时,一切都按预期工作,我的 book 被服务方法检查是否有违规行为。

现在假设我有第二个端点 (/method-validation),它接收另一个 object、MessedTitleBook,(把它想象成书名中也嵌入了作者) 我需要对其进行翻译以删除作者,然后将该书传递给私有方法以执行某些操作。在私有方法中,我需要检查翻译的书是否有效,但 @Valid 注释似乎不适用于私有方法。

问题:

  1. @Valid 是否适用于私有方法?如果没有,请提供我学习的资源。
  2. 有没有一种无需手动验证即可自动实现验证的方法,即注入 validator 并执行 validator.validate(book)

编辑
我忘了提及将方法范围从 private 更改为 public 可以使验证工作。

我不能保证这是您使用的库的 100% 正确答案,但我会继续并假设它的工作方式与 Spring 处理此类验证的方式类似。

对问题 1 的简短回答:不,它不起作用。

这种验证的处理方式通常是通过 AOP 代理实例的概念,它围绕着您的实际对象实例并拦截对其进行的所有调用,并且能够向其中添加额外的逻辑在将调用传递给 actual 对象实例之前执行,如验证参数。 这意味着 AOP 代理实例将(并且应该)只能处理 class.

的 public 接口

想一想,一旦调用“成功”到实际的实现实例,您的实例就会在该实例内部“内部”调用私有方法。这样 AOP 代理就无法拦截该调用以添加您想要的逻辑。

我认为在大量使用 Java 反射的帮助下,可能仍然有一些方法可以实现它,但我建议不要这样做,并使用注入的 validator 实例代替。 或者,正如您在示例中所描述的,一种处理 public 接口验证的验证器服务。

这里有一个关于 Javax Validation api 的指南,javax 验证将在任何具有 @Valid 注释的参数的 public 方法上自动调用。

虽然它非常灵活,因为您可以选择使用此验证或您已经找到的手动验证。

可以编写自定义验证器而不是使用注释来进行更复杂的验证。

至于您的问题,您已经知道它适用于 public 方法。 Javax 验证与 Jax-RS 集成,它允许您使用 @Valid 注释来注释您的 rest 方法参数,它会自动生成一个 400 响应,其中包含模型中错误的详细摘要。

Here 这也是一个 quarkus 指南。