【问题标题】:Javax validation on private method does not get triggered私有方法上的 Javax 验证不会被触发
【发布时间】:2021-09-28 09:54:31
【问题描述】:

假设我有一个非常简单的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 上发布Book 时,一切正常,服务方法会检查我的book 是否存在违规行为。

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

问题:

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

编辑
我忘了提到将方法范围从私有更改为公共可以使验证工作。

【问题讨论】:

    标签: java quarkus hibernate-validator


    【解决方案1】:

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

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

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

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

    Here 它也是一个 quarkus 指南。

    【讨论】:

    • 感谢您的回答和验证 api Javier 的链接!是的,如果您仔细观察,我的“示例”会被 quarkus 指南严重掩盖:D
    【解决方案2】:

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

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

    通常处理这种验证的方式是通过 AOP 代理实例的概念,它围绕您的实际对象实例进行包装并拦截对其进行的所有调用,这样就能够为执行添加额外的逻辑,就像验证参数一样,在将调用传递给 actual 对象实例之前。 这意味着 AOP 代理实例将(并且应该)只能处理类的公共接口。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      相关资源
      最近更新 更多