深入了解Hibernate Validator Annotation Processor

2023/05/12

1. 概述

很容易误用bean 验证约束。例如,我们可能不小心用@Future约束修饰了一个String属性。此类错误会导致运行时出现不可预知的错误。

幸运的是,Hibernate Validator Annotation Processor有助于在编译时检测这些问题。由于它抛出的错误,我们可以更早地发现这些错误。

在本教程中,我们将探索如何配置处理器,并查看它可以为我们找到的一些常见问题。

2.配置

2.1. 安装

让我们从将注解处理器依赖项添加到我们的 pom.xml 开始:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerArgs>
            <arg>-Averbose=true</arg>
            <arg>-AmethodConstraintsSupported=true</arg>
            <arg>-AdiagnosticKind=ERROR</arg>
        </compilerArgs>
        <annotationProcessorPaths>
            <path>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator-annotation-processor</artifactId>
                <version>6.2.0.Final</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

我们应该注意,此工具的版本 7 仅与jakarta.validation约束兼容:

<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
    <version>3.0.1</version>
</dependency>

该处理器还提供有关如何针对主要JavaIDE 进行设置的指南。

2.2. 编译器选项

让我们设置我们的处理器编译器选项:

<compilerArgs>
    <arg>-Averbose=true</arg>
    <arg>-AmethodConstraintsSupported=true</arg>
    <arg>-AdiagnosticKind=ERROR</arg>
</compilerArgs>

首先,diagnosticKind选项针对日志记录级别。最好保留默认的ERROR值,以便在编译时发现问题。Diagnostic.Kind枚举中引用了所有允许的值。

接下来,如果我们只想将注解验证限制为 getter,我们应该将methodConstraintsSupported选项设置为false。

在这里,我们将verbose设置为true以获得更多输出,但如果我们不想要大量日志输出,我们可以将其设置为false 。

3. 常见的约束问题

注解处理器带有一组要检查的预定义错误。让我们以一个简单的Message类为例,仔细看看其中的三个:

public class Message {
    // constructor omitted
}

3.1. 只能注解 getter

首先,处理器的默认选项不应该存在这个问题。顾名思义,当我们注解一个非getter方法时,它就会弹出。我们需要将methodConstraintsSupported选项设置为true以允许这样做。

让我们向Message类添加三个带注解的方法:

@Min(3)
public boolean broadcast() {
    return true;
}

@NotNull
public void archive() {
}

@AssertTrue
public boolean delete() {
    return false;
}

接下来,我们在配置中将 methodConstraintsSupported选项设置为false:

<compilerArgs>
    <arg>AmethodConstraintsSupported=false</arg>
</compilerArgs>

最后,这三种方法将使处理器检测到我们的问题:

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalmethodvalidationmodelReservationManagement.java:[25,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[55,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[38,5] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[47,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[INFO] 4 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.457 s
[INFO] Finished at: 2022-01-20T21:42:47Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure: Compilation failure:
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalmethodvalidationmodelReservationManagement.java:[25,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[55,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[38,5] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[47,4] error: Constraint annotations must not be specified at methods, which are no valid JavaBeans getter methods.

有趣的是,删除方法受到该问题的影响,尽管从技术上讲,它已被正确注解。

对于接下来的部分,我们将把methodConstraintsSupported选项设置回true。

3.2. 只能注解非 Void 方法

这个问题表明我们不应该用约束验证来修饰void方法。我们可以通过在Message类中注解存档方法来查看它的实际效果:

@NotNull
public void archive() {
}

它会导致处理器引发错误:

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[45,4] error: Void methods may not be annotated with constraint annotations.
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.078 s
[INFO] Finished at: 2022-01-20T21:35:08Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[45,4] error: Void methods may not be annotated with constraint annotations.

3.3. 不支持的注解类型

最后一个问题是最常见的。它发生在注解目标数据类型与目标属性不匹配时。为了在我们的Message类中看到它的作用,让我们向我们的Message类添加一个错误注解的String属性:

@Past 
private String createdAt;

@Past注解会导致错误。事实上,只有日期类型可以使用这个约束:

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}baeldungtutorialsjavaxvalhibernatevalidatorapMessage.java:[20,5] error: The annotation @Past is disallowed for this data type.
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.892 s
[INFO] Finished at: 2022-01-20T21:29:15Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[20,5] error: The annotation @Past is disallowed for this data type.

如果我们将错误的注解应用于具有不受支持的返回类型的方法,我们将得到类似的错误:

@Min(3)
public boolean broadcast() { 
    return true;
}

处理器错误消息与上一个相同:

[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[37,5] error: The annotation @Min is disallowed for the return type of this method.
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.761 s
[INFO] Finished at: 2022-01-20T21:38:28Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project javaxval: Compilation failure
[ERROR] ${home}baeldungtutorialsjavaxvalsrcmainjavacombaeldungjavaxvalhibernatevalidatorapMessage.java:[37,5] error: The annotation @Min is disallowed for the return type of this method.

4. 总结

在本文中,我们尝试了 Hibernate Validator Annotation Processor。

首先,我们安装它并配置它的选项。然后,我们通过三个常见的约束问题探索了它的行为。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章