【翻译】Hibernate Validator 6.0.13.Final - JSR 380 参考实现

本文介绍了HibernateValidator作为BeanValidation的参考实现,演示了如何在Java项目中集成和使用该库进行数据验证,包括依赖配置、约束注解的使用及验证实例。

这是我正在翻译的内容,持续更新中,同名工程能在 github HibernateValidator6.0.13_zh上搜索到,欢迎加✨

Hibernate Validator 6.0.13.Final - JSR 380 参考实现:参考文档

Hibernate Validator 6.0.13.Final - JSR 380 Reference Implementation: Reference Guide

Hardy Ferentschik Gunnar Morling Guillaume Smet 2018-08-22

序言

数据校验功能是一个应用程序的常用功能,它发生在应用的从展示层到持久层的各个层面。我们经常会在各个层面使用相同的校验逻辑,而这样容易导致
时间浪费和容易出错。为了避免进行重复的校验,开发者经常把校验逻辑写在领域模型里面,这样又将领域模型的代码和校验代码杂糅在一起,而领域模型
应该只关乎元数据本身。

avatar

JSR 380 - Bean Validation 2.0 - 为了实体和方法的校验定义了元数据模型和 API。默认的元数据模型是通过注解来描述的,但是也可以通过XML配
置来重写和拓展元数据。这些 API 并没有限制在某一特定的应用层或者编程模型上,也没有限制在 web 层或持久层。而且既可以用在服务端应用,也可以用
在类似 Swing 这样的客户端。

avatar

Hibernate Validator 是 JSR 380 参考实现。Hibernate Validator、Bean Validation API 和 TCK 都是使用了Apache Software License
2.0。

Hibernate Validator 6 和 Bean Validation 2.0 需要 Java8 或更新版本。

1. 开始使用

这一章节将会告诉你如何开始使用 Hibernate Validator(Bean Validation 的参考实现)。你需要提前准备好这些:

  • JDK8
  • Apache Maven
  • 联网环境(Maven 需要下载一些必要的库)

1.1. 工程设置

为了在 Maven 工程中使用 Hibernate Validator,你只需要在 pom.xml 文件中添加下列依赖:

Example 1.1: Hibernate Validator Maven dependency

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.13.Final</version>
</dependency>

这也会将它的依赖 Bean Validation API (javax.validation:validation-api:2.0.1.Final)拉下来。

1.1.1. Unified EL 统一表达式语言

Hbernate Validator 需要统一表达式语言(JSR341)的实现来动态的评估违反限制的表达式(参见
Section 4.1, “Default message interpolation”)。当你的应用跑在一个类似 JBoss AS 的 Java EE 容器中时,容器已经提供了一个EL的实
现。但是在Java SE环境中,你需要通过在 POM 文件中添加一个依赖来自己添加 EL 的实现。例如,你可以添加以下的依赖来使用 JSR 341 参考实
:

Example 1.2: Maven dependencies for Unified EL reference implementation

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.el</artifactId>
    <version>3.0.1-b09</version>
</dependency>

提示

对于那些无法提供 EL 实现的环境,Hibernate Validator提供了 Section 12.9, “ParameterMessageInterpolator”。但是使用interpolator
并不符合 Bean Validation 的规范。

1.1.2. CDI

Bean Validation 使用了 CDI(JavaTM EE 的上下文和依赖注入,JSR346) 定义了整合点。如果你的应用所在的环境无法提供这
个,你可以通过添加一下的 Maven 依赖,来使用使用 Hibernate Validator CDI 可移植拓展。

Example 1.3: Hibernate Validator CDI portable extension Maven dependency

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-cdi</artifactId>
    <version>6.0.13.Final</version>
</dependency>

值得注意的是,大部分跑在 Java EE 环境上的应用是不需要添加这个依赖的。你可以在这 Section 11.3, “CDI” 获取更多关于Bean Validation
和 CDI 整合的内容。

1.1.3. 结合安全管理器运行

Hibernate Validator 支持与安全管理器一起启动,
为了实现这个功能,你必须到Hibernate Validator,Bean Validation API,Classmate and JBoss Logging 和 Bean Validation的代码底层
去分配一些许可权限。下面展示了如何通过一个加工过的 Java 默认 policy 文件 policy file
来实现这个功能。

Example 1.4: Policy file for using Hibernate Validator with a security manager

grant codeBase "file:path/to/hibernate-validator-6.0.13.Final.jar" {
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
    permission java.lang.RuntimePermission "accessDeclaredMembers";
    permission java.lang.RuntimePermission "setContextClassLoader";

    permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers";

    // Only needed when working with XML descriptors (validation.xml or XML constraint mappings)
    permission java.util.PropertyPermission "mapAnyUriToUri", "read";
};

grant codeBase "file:path/to/validation-api-2.0.1.Final.jar" {
    permission java.io.FilePermission "path/to/hibernate-validator-6.0.13.Final.jar", "read";
};

grant codeBase "file:path/to/jboss-logging-3.3.2.Final.jar" {
    permission java.util.PropertyPermission "org.jboss.logging.provider", "read";
    permission java.util.PropertyPermission "org.jboss.logging.locale", "read";
};

grant codeBase "file:path/to/classmate-1.3.4.jar" {
    permission java.lang.RuntimePermission "accessDeclaredMembers";
};

grant codeBase "file:path/to/validation-caller-x.y.z.jar" {
    permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers";
};

WildFly 应用程序服务器包含了开箱即用的 Hibernate Validator。为了升级服务器模块到最新最好的Bean Validation
API 和 Hibernate Validator,可以使用 WildFly 的补丁。你可以从 SourceForge
上下载补丁文件,也可以使用以下依赖从 Maven 中央仓库下载。

Example 1.5: Maven dependency for WildFly 14.0.0.Beta1 patch file

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-modules</artifactId>
    <version>6.0.13.Final</version>
    <classifier>wildfly-14.0.0.Beta1-patch</classifier>
    <type>zip</type>
</dependency>

我们也为 WildFly 13.0.0.Final 提供了一个补丁:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-modules</artifactId>
    <version>6.0.13.Final</version>
    <classifier>wildfly-13.0.0.Final-patch</classifier>
    <type>zip</type>
</dependency>

下载补丁文件后,你可以通过以下命令将它应用于 WildFly 上:

Example 1.7: Applying the WildFly patch

$JBOSS_HOME/bin/jboss-cli.sh patch apply hibernate-validator-modules-6.0.13.Final-wildfly-14.0.0.Beta1-patch.zip

如果你想回退补丁,使用服务器提供的原生 Hibernate Validator 版本,你可以使用以下的命令:

Example 1.8: Rolling back the WildFly patch

$JBOSS_HOME/bin/jboss-cli.sh patch rollback --reset-configuration=true

你可以在这里
这里了解到更多关于
WildFly 补丁的情况。

1.1.5. 在 Java 9 上运行

Hibernate Validator 6.0.13.Final 对于 Java 9 和 Java平台模块化系统(JPMS)的支持是实验性质的。这里还没有提供 JPMS 的模块描述器
提供,但是 Hibernate Validator 能够作为一个自动模块。

以下是声明使用Automatic-Module-Name头的模块名:

  • Bean Validation API: java.validation

  • Hibernate Validator core: org.hibernate.validator

  • Hibernate Validator CDI extension: org.hibernate.validator.cdi

  • Hibernate Validator test utilities: org.hibernate.validator.testutils

  • Hibernate Validator annotation processor: org.hibernate.validator.annotationprocessor

这些模块名可能是暂定的,在未来版本提供真实的模块描述器时可能会改名。

注意

当同时使用 Hibernate Validator 和 CDI 时,小心不要激活 JDK 的 java.xml.ws.annotation 模块。这个模块包含了一个有 JSR 250 API
(“常见注解”)的子集,但是例如有些注解 javax.annotation.Priority 却缺失了。这就造成了 Hibernate Validator 的方法校验拦截器不能
被注册,也就是说:方法校验失效。

可行的方法是添加完全版的 JSR 250 API 到你的模块(就是添加到classpath),例如添加 javax.annotation:javax.annotation-api
依赖(当依赖 org.hibernate.validator:hibernate-validator-cdi 时,已经有可使用的 JSR 250 API 依赖了)。

如果你因为某些原因不得不使用 java.xml.ws.annotation 模块,你应该在你的 Java 中通过添加 --patch-module java.xml.ws.annotation=/path/to/complete-jsr250-api.jar
来打上 API 的完全补丁。

1.2. 使用约束

让我们直接通过一个例子来看看如何使用这些约束吧。

Example 1.9: Class Car annotated with constraints

package org.hibernate.validator.referenceguide.chapter01;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Car {

    @NotNull
    private String manufacturer;

    @NotNull
    @Size(min = 2, max = 14)
    private String licensePlate;

    @Min(2)
    private int seatCount;

    public Car(String manufacturer, String licencePlate, int seatCount) {
        this.manufacturer = manufacturer;
        this.licensePlate = licencePlate;
        this.seatCount = seatCount;
    }

    //getters and setters ...
}

注解 @NotNull@Size@Min 应该被用在 Car 类的成员变量上,用来施加以下的约束:

  • manufacture 必须非空
  • licensePlate 必须非空,且长度在2~14个字符之间
  • seatCount 最小值为2

提示

你能在 GitHub 中的 Hibernate Validator 代码库中找到所有例子的完整源代码。

1.3. 校验约束

为了校验这些约束,你需要使用一个 Validator 实例。让我们来看一个 Car 的单元测试:

Example 1.10: Class CarTest showing validation examples

package org.hibernate.validator.referenceguide.chapter01;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class CarTest {

    private static Validator validator;

    @BeforeClass
    public static void setUpValidator() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

    @Test
    public void manufacturerIsNull() {
        Car car = new Car( null, "DD-AB-123", 4 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 1, constraintViolations.size() );
        assertEquals( "must not be null", constraintViolations.iterator().next().getMessage() );
    }

    @Test
    public void licensePlateTooShort() {
        Car car = new Car( "Morris", "D", 4 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 1, constraintViolations.size() );
        assertEquals(
                "size must be between 2 and 14",
                constraintViolations.iterator().next().getMessage()
        );
    }

    @Test
    public void seatCountTooLow() {
        Car car = new Car( "Morris", "DD-AB-123", 1 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 1, constraintViolations.size() );
        assertEquals(
                "must be greater than or equal to 2",
                constraintViolations.iterator().next().getMessage()
        );
    }

    @Test
    public void carIsValid() {
        Car car = new Car( "Morris", "DD-AB-123", 2 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 0, constraintViolations.size() );
    }
}

setUpValidator() 方法中,从 ValidatorFactory 中取出了一个 Validator 对象。一个 Validator 实例是线程安全的,并且可以
被多次使用。所以能把它安全的放在一个静态变量中,然后在测试方法中用它来多次校验不同的 Car 实例。

Validate() 方法会返回一个 ConstraintViolation 实例的集合,你能够遍历这个集合,来查看哪个校验错误发生了。前三个测试方法展示了一
我们可预见的校验错误:

  • manufacturerIsNull()manufacture 违反了非空 @NotNull 的约束
  • licensePlateTooShort()licensePlate 违反了大小 @Size 的约束
  • seatCountTooLow()seatCount 违反了最小值 @Min 的约束

carIsValid() 中所示,如果对象校验成功,那么 validate() 将会返回一个空集。

注意到以上的代码只使用了 javax.validation 包中的类。这些是 Bean Validation API 提供的。没有 Hibernate Validator 中的类被直接
使用,这让代码可移植行更好。

1.4. 接下来会有什么?

我们结束了对 Hibernate Validator 和 Bean Validation 的5分钟探索。如果需要继续查看代码例子或者看更多的例子,请参考 第14章,更多阅读

如果你想要了解更多关于 bean 和属性的校验问题,请继续阅读 第2章,声明并校验 bean 上的约束。如果你想要了解使用 Bean Validation 对
方法进行前置或后置校验,请参考 第3章,声明并校验方法上的约束。如果你想在你的应用中加上自定义的校验,你可以看看 第6章,创造自定义约束

2. 声明并校验 bean 上的约束

C:\Users\Administrator\.jdks\ms-17.0.15\bin\java.exe "-javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2025.1\captureAgent\debugger-agent.jar=file:///C:/Users/ADMINI~1/AppData/Local/Temp/capture14296932213736813194.props" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Users\Administrator\AppData\Local\Programs\IntelliJ IDEA Ultimate 2025.1.3\lib\idea_rt.jar=53606" -Dkotlinx.coroutines.debug.enable.creation.stack.trace=false -Ddebugger.agent.enable.coroutines=true -Dkotlinx.coroutines.debug.enable.flows.stack.trace=true -Dkotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace=true -Dfile.encoding=UTF-8 -classpath "C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-launcher\1.9.3\junit-platform-launcher-1.9.3.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-engine\1.9.3\junit-platform-engine-1.9.3.jar;C:\Users\Administrator\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-commons\1.9.3\junit-platform-commons-1.9.3.jar;C:\Users\Administrator\.m2\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;C:\Users\Administrator\AppData\Local\Programs\IntelliJ IDEA Ultimate 2025.1.3\lib\idea_rt.jar;C:\Users\Administrator\AppData\Local\Programs\IntelliJ IDEA Ultimate 2025.1.3\plugins\junit\lib\junit5-rt.jar;C:\Users\Administrator\AppData\Local\Programs\IntelliJ IDEA Ultimate 2025.1.3\plugins\junit\lib\junit-rt.jar;C:\Users\Administrator\IdeaProjects\SpringTest\target\test-classes;C:\Users\Administrator\IdeaProjects\SpringTest\target\classes;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-starter-web\3.1.5\spring-boot-starter-web-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-starter\3.1.5\spring-boot-starter-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot\3.1.5\spring-boot-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-autoconfigure\3.1.5\spring-boot-autoconfigure-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-starter-logging\3.1.5\spring-boot-starter-logging-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\ch\qos\logback\logback-classic\1.4.11\logback-classic-1.4.11.jar;D:\apache-maven-3.9.10\maven-repository\ch\qos\logback\logback-core\1.4.11\logback-core-1.4.11.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\logging\log4j\log4j-to-slf4j\2.20.0\log4j-to-slf4j-2.20.0.jar;D:\apache-maven-3.9.10\maven-repository\org\slf4j\jul-to-slf4j\2.0.9\jul-to-slf4j-2.0.9.jar;D:\apache-maven-3.9.10\maven-repository\jakarta\annotation\jakarta.annotation-api\2.1.1\jakarta.annotation-api-2.1.1.jar;D:\apache-maven-3.9.10\maven-repository\org\yaml\snakeyaml\1.33\snakeyaml-1.33.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-starter-json\3.1.5\spring-boot-starter-json-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\jackson\core\jackson-databind\2.15.3\jackson-databind-2.15.3.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\jackson\core\jackson-annotations\2.15.3\jackson-annotations-2.15.3.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\jackson\core\jackson-core\2.15.3\jackson-core-2.15.3.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.15.3\jackson-datatype-jdk8-2.15.3.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.15.3\jackson-datatype-jsr310-2.15.3.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.15.3\jackson-module-parameter-names-2.15.3.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-starter-tomcat\3.1.5\spring-boot-starter-tomcat-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\tomcat\embed\tomcat-embed-core\10.1.15\tomcat-embed-core-10.1.15.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\tomcat\embed\tomcat-embed-el\10.1.15\tomcat-embed-el-10.1.15.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\tomcat\embed\tomcat-embed-websocket\10.1.15\tomcat-embed-websocket-10.1.15.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-web\6.0.13\spring-web-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\io\micrometer\micrometer-observation\1.11.5\micrometer-observation-1.11.5.jar;D:\apache-maven-3.9.10\maven-repository\io\micrometer\micrometer-commons\1.11.5\micrometer-commons-1.11.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-webmvc\6.0.13\spring-webmvc-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-aop\6.0.13\spring-aop-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-context\6.0.13\spring-context-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-expression\6.0.13\spring-expression-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-starter-test\3.1.5\spring-boot-starter-test-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-test\3.1.5\spring-boot-test-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\boot\spring-boot-test-autoconfigure\3.1.5\spring-boot-test-autoconfigure-3.1.5.jar;D:\apache-maven-3.9.10\maven-repository\com\jayway\jsonpath\json-path\2.8.0\json-path-2.8.0.jar;D:\apache-maven-3.9.10\maven-repository\jakarta\xml\bind\jakarta.xml.bind-api\4.0.1\jakarta.xml.bind-api-4.0.1.jar;D:\apache-maven-3.9.10\maven-repository\jakarta\activation\jakarta.activation-api\2.1.2\jakarta.activation-api-2.1.2.jar;D:\apache-maven-3.9.10\maven-repository\net\minidev\json-smart\2.4.11\json-smart-2.4.11.jar;D:\apache-maven-3.9.10\maven-repository\net\minidev\accessors-smart\2.4.11\accessors-smart-2.4.11.jar;D:\apache-maven-3.9.10\maven-repository\org\ow2\asm\asm\9.3\asm-9.3.jar;D:\apache-maven-3.9.10\maven-repository\org\assertj\assertj-core\3.24.2\assertj-core-3.24.2.jar;D:\apache-maven-3.9.10\maven-repository\net\bytebuddy\byte-buddy\1.14.9\byte-buddy-1.14.9.jar;D:\apache-maven-3.9.10\maven-repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;D:\apache-maven-3.9.10\maven-repository\org\junit\jupiter\junit-jupiter\5.9.3\junit-jupiter-5.9.3.jar;D:\apache-maven-3.9.10\maven-repository\org\junit\jupiter\junit-jupiter-params\5.9.3\junit-jupiter-params-5.9.3.jar;D:\apache-maven-3.9.10\maven-repository\org\junit\jupiter\junit-jupiter-engine\5.9.3\junit-jupiter-engine-5.9.3.jar;D:\apache-maven-3.9.10\maven-repository\org\junit\platform\junit-platform-engine\1.9.3\junit-platform-engine-1.9.3.jar;D:\apache-maven-3.9.10\maven-repository\org\mockito\mockito-core\5.3.1\mockito-core-5.3.1.jar;D:\apache-maven-3.9.10\maven-repository\net\bytebuddy\byte-buddy-agent\1.14.9\byte-buddy-agent-1.14.9.jar;D:\apache-maven-3.9.10\maven-repository\org\objenesis\objenesis\3.3\objenesis-3.3.jar;D:\apache-maven-3.9.10\maven-repository\org\mockito\mockito-junit-jupiter\5.3.1\mockito-junit-jupiter-5.3.1.jar;D:\apache-maven-3.9.10\maven-repository\org\skyscreamer\jsonassert\1.5.1\jsonassert-1.5.1.jar;D:\apache-maven-3.9.10\maven-repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-core\6.0.13\spring-core-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-jcl\6.0.13\spring-jcl-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\xmlunit\xmlunit-core\2.9.1\xmlunit-core-2.9.1.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-test\6.0.2\spring-test-6.0.2.jar;D:\apache-maven-3.9.10\maven-repository\org\junit\jupiter\junit-jupiter-api\5.6.3\junit-jupiter-api-5.6.3.jar;D:\apache-maven-3.9.10\maven-repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;D:\apache-maven-3.9.10\maven-repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;D:\apache-maven-3.9.10\maven-repository\org\junit\platform\junit-platform-commons\1.9.3\junit-platform-commons-1.9.3.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\logging\log4j\log4j-slf4j2-impl\2.23.1\log4j-slf4j2-impl-2.23.1.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\logging\log4j\log4j-api\2.20.0\log4j-api-2.20.0.jar;D:\apache-maven-3.9.10\maven-repository\org\slf4j\slf4j-api\2.0.9\slf4j-api-2.0.9.jar;D:\apache-maven-3.9.10\maven-repository\org\apache\logging\log4j\log4j-core\2.20.0\log4j-core-2.20.0.jar;D:\apache-maven-3.9.10\maven-repository\com\alibaba\fastjson2\fastjson2-extension\2.0.9\fastjson2-extension-2.0.9.jar;D:\apache-maven-3.9.10\maven-repository\com\alibaba\fastjson2\fastjson2\2.0.9\fastjson2-2.0.9.jar;D:\apache-maven-3.9.10\maven-repository\com\mysql\mysql-connector-j\8.0.33\mysql-connector-j-8.0.33.jar;D:\apache-maven-3.9.10\maven-repository\com\alibaba\druid\1.2.1\druid-1.2.1.jar;D:\apache-maven-3.9.10\maven-repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-jdbc\6.0.13\spring-jdbc-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-beans\6.0.13\spring-beans-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\springframework\spring-tx\6.0.13\spring-tx-6.0.13.jar;D:\apache-maven-3.9.10\maven-repository\org\hibernate\validator\hibernate-validator\8.0.1.Final\hibernate-validator-8.0.1.Final.jar;D:\apache-maven-3.9.10\maven-repository\jakarta\validation\jakarta.validation-api\3.0.2\jakarta.validation-api-3.0.2.jar;D:\apache-maven-3.9.10\maven-repository\org\jboss\logging\jboss-logging\3.5.3.Final\jboss-logging-3.5.3.Final.jar;D:\apache-maven-3.9.10\maven-repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\apache-maven-3.9.10\maven-repository\org\glassfish\jakarta.el\4.0.1\jakarta.el-4.0.1.jar;D:\apache-maven-3.9.10\maven-repository\jakarta\el\jakarta.el-api\4.0.0\jakarta.el-api-4.0.0.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.yxq.springtest.SpringControlerTest,test Internal Error occurred. org.junit.platform.commons.JUnitException: TestEngine with ID 'junit-jupiter' failed to discover tests at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:160) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverSafely(EngineDiscoveryOrchestrator.java:132) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:107) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:78) at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:110) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:231) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) Caused by: java.lang.NoClassDefFoundError: org/junit/jupiter/api/io/CleanupMode at org.junit.jupiter.engine.JupiterTestEngine.discover(JupiterTestEngine.java:66) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:152) ... 13 more Caused by: java.lang.ClassNotFoundException: org.junit.jupiter.api.io.CleanupMode at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ... 15 more 进程已结束,退出代码为 -2 这个报错怎么解决
最新发布
09-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值