CentOS 8 安装 Apache BVal 指南
在 CentOS 8 从零安装 Apache BVal 3.0.2:vault 源、JDK 17 与 Maven 安装及 alternatives/JAVA_HOME 切换、Maven 依赖与手动双 jar 两方案、sha1 校验、多版本管理与卸载,全程实测。
CentOS 8 安装 Apache BVal 指南
目标:在 CentOS 8 服务器上从零搭建可编译、可运行 Apache BVal(Jakarta Bean Validation 参考实现之一)的 Java 环境,覆盖「Maven 依赖」与「Maven Central 手动双 jar」两种方案、sha1 完整性校验、最小验证代码、多 JDK/Maven 切换与卸载,已在 CentOS 8.4(OpenJDK 17.0.1、Maven 3.5.4)实测通过。
一、环境信息
本篇所有命令与回显均在以下环境中实测采集,复现时请保持相近版本:
- 操作系统:CentOS Linux 8.4.2105,x86_64
- JDK:OpenJDK 17.0.1(
java-17-openjdk-devel,系统仓库;系统另预装 OpenJDK 1.8.0_312) - 构建工具:Apache Maven 3.5.4(
maven,系统仓库,Red Hat 定制版) - 组件版本:Apache BVal 3.0.2(
org.apache.bval:bval-jsr,Maven 中央仓库当前最新稳定版,2026-10 实测) - 校验工具:coreutils sha1sum(Maven Central 为 BVal 提供
.sha1校验文件) - 实验目录:
/opt/bval-demo - 执行用户:root
二、前置条件
本节确认系统版本、软件源可用性与基础工具。CentOS 8 已于 2021 年底停止维护,官方源下线后必须切换到 vault 归档源,这是 CentOS 8 安装任何软件的第一道门槛。
2.1 确认系统版本与源状态
cat /etc/redhat-release
回显(实测):
CentOS Linux release 8.4.2105
检查源指向是否为 vault 归档(本机已切换,指向清华大学 vault 镜像):
grep -h baseurl /etc/yum.repos.d/CentOS-Linux-AppStream.repo /etc/yum.repos.d/CentOS-Linux-BaseOS.repo
回显(实测):
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111/AppStream/x86_64/os/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111/BaseOS/x86_64/os/
若你的机器仍指向已下线的 mirror.centos.org,执行下面这条把官方源地址整体替换为 vault 路径:
sed -i -e 's|mirror.centos.org|vault.centos.org|g' -e 's|^#baseurl=http://vault|baseurl=http://vault|g' /etc/yum.repos.d/CentOS-Linux-*.repo
回显(实测,sed 就地改写无输出):
dnf repolist
回显(实测):
repo id repo name
AppStream CentOS Linux 8 - AppStream
BaseOS CentOS Linux 8 - BaseOS
dnf repolist 能列出 AppStream 与 BaseOS 两个仓库即源可用。
2.2 安装基础工具
dnf install -y curl wget
回显(实测):
Package curl-7.61.1-22.el8.x86_64 is already installed.
Package wget-1.19.5-10.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
本机已随系统预装 curl 与 wget,dnf 判定无需新装、直接以 Nothing to do 收尾;全新系统这一步会列出待安装明细,同样以 Complete! 结束。
curl --version | head -1
回显(实测):
curl 7.61.1 (x86_64-redhat-linux-gnu) libcurl/7.61.1 OpenSSL/1.1.1k zlib/1.2.11 nghttp2/1.33.0
curl 版本正常输出,基础工具就绪。
三、版本选型说明
BVal 是纯 Java 库(Jakarta Bean Validation 实现),没有独立进程,选型核心是「库版本 + 命名空间(javax/jakarta)+ JDK 版本」三者匹配。先实测 Maven 中央仓库当前最新版本:
curl -s 'https://search.maven.org/solrsearch/select?q=g:org.apache.bval%20AND%20a:bval-jsr&rows=5&wt=json&core=gav' | grep -oE '"v":"[^"]+"' | head -5
回显(实测):
"v":"3.0.2"
"v":"3.0.1"
"v":"3.0.0"
"v":"2.0.6"
"v":"2.0.5"
版本与命名空间对照如下(SPI 服务文件名与 MANIFEST 均为实测,见 5.5 节):
| 组件 | 版本 | 验证 API 命名空间 | JDK 要求 | 获取渠道 | 说明 |
|---|---|---|---|---|---|
| BVal (bval-jsr) | 3.0.2 | jakarta.validation(Jakarta Bean Validation 3.0) | Java 11+ 编译运行 | Maven 中央仓库 | 本文采用,最新稳定版 |
| BVal (bval-jsr) | 2.0.6 | javax.validation(Bean Validation 2.0) | Java 8+ | Maven 中央仓库 / downloads.apache.org(仅源码包) | 存量 javax 工程常见 |
| JDK | OpenJDK 17.0.1(LTS) | — | — | CentOS 8 系统仓库 java-17-openjdk | 编译与运行示例均正常 |
| Maven | 3.5.4 | — | Java 8+ | CentOS 8 系统仓库 | 方案 A 依赖解析使用 |
关键差异与选型建议:BVal 自 3.0.0 起切换到 jakarta.validation 命名空间,2.0.x 及更早是 javax.validation,两者不能混用(会报找不到 Provider 或类缺失);新工程直接用最新 3.0.2,维护老 javax 工程时选 2.0.6。另需注意:BVal 在官方下载站 downloads.apache.org/bval/ 只提供源码发行包(最新为 2.0.6 的 bval-parent-2.0.6-source-release.zip,实测确认 3.0.2 无独立二进制发行包),二进制 jar 的官方渠道就是 Maven 中央仓库,这与 Commons Codec 等自带 bin tarball 的项目不同。
四、安装方案 A:Maven 依赖安装(在线,推荐)
方案 A 通过 Maven 中央仓库自动拉取 bval-jsr 及验证 API jar,依赖集中在 pom.xml 管理。CentOS 8 的特殊性在于系统预装了 Java 8 且 Maven 绑定 JAVA_HOME,本节会同时处理「alternatives 切 JDK」与「Maven 实际使用的 JDK」两个问题。
4.1 安装 JDK 17 与 Maven
一条命令装齐编译运行所需组件:
dnf install -y java-17-openjdk-devel maven
输出节选(实测,Installed 列表共 135 个包,仅列本文关心的条目):
Installed:
java-17-openjdk-1:17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-devel-1:17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-headless-1:17.0.1.0.12-2.el8_5.x86_64
maven-1:3.5.4-5.module_el8.0.0+39+6a9b6e22.noarch
java-1.8.0-openjdk-1:1.8.0.312.b07-2.el8_5.x86_64
Complete!
注:CentOS 8 的 maven module 会把 javapackages-tools 依赖的 Java 8(java-1.8.0-openjdk)一并带入——系统预装 Java 8 的机器上它是已存在状态,新装机器会同时获得 8 与 17 两个 JDK,因此 4.2 节的默认 JDK 切换是必需步骤。
验证安装(注意此时默认 java 可能仍是预装的 1.8):
java -version 2>&1 | head -1
回显(实测,安装后未切换时):
openjdk version "1.8.0_312"
4.2 alternatives 切换默认 JDK
列出可用的 JDK 并把默认 java 切到 17:
alternatives --set java java-17-openjdk.x86_64 && java -version 2>&1 | head -1
回显(实测):
openjdk version "17.0.1" 2021-10-19 LTS
java 命令已是 17,但 Maven 不一定跟着变——mvn 通过 JAVA_HOME 找 JDK,此时 mvn -version 实测仍显示 Java 8:
mvn -version 2>&1 | head -4
回显(实测,未设置 JAVA_HOME 时):
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 1.8.0_312, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-2.el8_5.x86_64/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
为 Maven 显式指定 JDK 17(写入 /etc/profile.d 使其永久生效):
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk' > /etc/profile.d/java17.sh && echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile.d/java17.sh && source /etc/profile.d/java17.sh && mvn -version 2>&1 | head -3
回显(实测):
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 17.0.1, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-17-openjdk-17.0.1.0.12-2.el8_5.x86_64
Maven 的 runtime 已切到 17.0.1。若跳过这一步,后续编译按 Java 17 目标构建时会报 invalid target release: 17(真实失败样例见第八节 FAQ Q1)。
4.3 创建工程与 pom.xml
mkdir -p /opt/bval-demo/src/main/java/demo
回显(实测,无输出即成功):
cat > /opt/bval-demo/pom.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>bval-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-jsr</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-extras</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
</project>
EOF
回显(实测,无输出即成功):
pom 逐项说明:maven.compiler.source/target 设为 17 与 JDK 对齐(BVal 3.0.x 自身字节码为 Java 11,见 5.5 节 MANIFEST,故 JDK 11 以上即可运行);project.build.sourceEncoding 固定 UTF-8。三个依赖中,bval-jsr:3.0.2 是校验实现本体,bval-extras:3.0.2 是 BVal 提供的扩展约束库(银行卡/IBAN/IP 等校验位算法),jakarta.validation-api:3.0.2 是 Jakarta Bean Validation 3.0 规范 API——必须显式引入,因为 bval-jsr 的 POM 中该依赖 scope 为 provided(设计上预期由容器提供),独立应用不写它就编译不过。
4.4 编译并解析依赖
cd /opt/bval-demo && mvn compile
输出节选(实测首尾):
[INFO] ---------------------------< demo:bval-demo >---------------------------
[INFO] Building bval-demo 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ bval-demo ---
[INFO] Compiling 1 source file to /opt/bval-demo/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
核对 jar 已落入本地仓库:
ls /root/.m2/repository/org/apache/bval/bval-jsr/3.0.2/ /root/.m2/repository/jakarta/validation/jakarta.validation-api/3.0.2/
回显(实测):
/root/.m2/repository/jakarta/validation/jakarta.validation-api/3.0.2/:
jakarta.validation-api-3.0.2.jar jakarta.validation-api-3.0.2.pom _remote.repositories
/root/.m2/repository/org/apache/bval/bval-jsr/3.0.2/:
bval-jsr-3.0.2.jar bval-jsr-3.0.2.pom _remote.repositories
BUILD SUCCESS 且本地仓库出现两个 jar,依赖解析完成。
4.5 最小验证代码
写一个仅依赖 BVal 的验证类,覆盖「非法对象报违反 + 合法对象零违反」闭环:
cat > /opt/bval-demo/src/main/java/demo/BvalDemo.java <<'EOF'
package demo;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.constraints.*;
import java.util.Set;
public class BvalDemo {
public static class User {
@NotNull(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度须在 {min}-{max} 之间")
private String username;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不合法")
private String email;
@Min(value = 18, message = "年龄不能小于 {value}")
@Max(value = 120, message = "年龄不能大于 {value}")
private Integer age;
@Pattern(regexp = "1[3-9]\\d{9}", message = "手机号格式不合法")
private String phone;
public User(String username, String email, Integer age, String phone) {
this.username = username; this.email = email; this.age = age; this.phone = phone;
}
public String getUsername() { return username; }
public String getEmail() { return email; }
public Integer getAge() { return age; }
public String getPhone() { return phone; }
}
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
System.out.println("ValidatorFactory 实现类: " + factory.getClass().getName());
User bad = new User("ab", "not-an-email", 15, "12345");
Set<ConstraintViolation<User>> violations = validator.validate(bad);
System.out.println("非法对象约束违反数: " + violations.size());
for (ConstraintViolation<User> v : violations) {
System.out.println(" [" + v.getPropertyPath() + "] " + v.getMessage()
+ " | 无效值 = " + v.getInvalidValue());
}
User good = new User("zhangsan", "zhangsan@example.com", 30, "13800138000");
System.out.println("合法对象约束违反数: " + validator.validate(good).size());
factory.close();
}
}
EOF
回显(实测,无输出即成功):
编译并运行(Maven 编译后用最小 classpath 直跑,验证 4.6 节的双 jar 事实):
cd /opt/bval-demo && java -Dfile.encoding=UTF-8 -cp "target/classes:/root/.m2/repository/org/apache/bval/bval-jsr/3.0.2/bval-jsr-3.0.2.jar:/root/.m2/repository/jakarta/validation/jakarta.validation-api/3.0.2/jakarta.validation-api-3.0.2.jar" demo.BvalDemo
回显(实测):
ValidatorFactory 实现类: org.apache.bval.jsr.ApacheValidatorFactory
非法对象约束违反数: 4
[phone] 手机号格式不合法 | 无效值 = 12345
[username] 用户名长度须在 3-20 之间 | 无效值 = ab
[email] 邮箱格式不合法 | 无效值 = not-an-email
[age] 年龄不能小于 18 | 无效值 = 15
合法对象约束违反数: 0
运行不需要手动注册 SPI 文件——bval-jsr jar 内自带 META-INF/services/jakarta.validation.spi.ValidationProvider,buildDefaultValidatorFactory() 通过 SPI 自动发现 ApacheValidationProvider。四条违反逐一命中、消息模板 {min}-{max}/{value} 正确插值,方案 A 验证通过(validate() 返回的是 Set,违反条目顺序不固定,多次运行顺序可能不同属正常现象)。
4.6 最小运行 classpath:双 jar 即可
上一步 classpath 只放了 bval-jsr 与 jakarta.validation-api 两个 jar,运行即成功。实测确认 bval-jsr 3.0.2 的 POM 中 commons-lang3、jakarta.activation-api 等其余依赖均为 provided 或 optional,基础校验路径不触发,独立应用最小运行时只需双 jar。用 Maven 核对实际解析到的依赖树:
cd /opt/bval-demo && mvn dependency:tree -DoutputFile=/tmp/tree.txt >/dev/null 2>&1; cat /tmp/tree.txt
回显(实测):
demo:bval-demo:jar:1.0.0
+- org.apache.bval:bval-jsr:jar:3.0.2:compile
+- org.apache.bval:bval-extras:jar:3.0.2:compile
\- jakarta.validation:jakarta.validation-api:jar:3.0.2:compile
树中无其他 compile 依赖,印证双 jar 结论。
五、安装方案 B:Maven Central 手动 jar 安装(不依赖构建工具)
方案 B 不依赖 Maven:直接从 Maven Central 下载双 jar,校验 sha1 后用 javac/java -cp 编译运行,适合无构建工具的服务器或离线环境。BVal 没有 bin 发行包(见第三节),Central 就是官方二进制渠道。
5.1 下载双 jar 与校验文件
mkdir -p /opt/bval-manual/lib && cd /opt/bval-manual/lib && wget -q https://repo1.maven.org/maven2/org/apache/bval/bval-jsr/3.0.2/bval-jsr-3.0.2.jar -O bval-jsr-3.0.2.jar && wget -q https://repo1.maven.org/maven2/org/apache/bval/bval-jsr/3.0.2/bval-jsr-3.0.2.jar.sha1 -O bval-jsr-3.0.2.jar.sha1 && wget -q https://repo1.maven.org/maven2/jakarta/validation/jakarta.validation-api/3.0.2/jakarta.validation-api-3.0.2.jar -O jakarta.validation-api-3.0.2.jar && wget -q https://repo1.maven.org/maven2/jakarta/validation/jakarta.validation-api/3.0.2/jakarta.validation-api-3.0.2.jar.sha1 -O jakarta.validation-api-3.0.2.jar.sha1 && ls -l
回显(实测):
total 832
-rw-r--r-- 1 root root 93298 Oct 13 07:32 jakarta.validation-api-3.0.2.jar
-rw-r--r-- 1 root root 41 Oct 13 07:32 jakarta.validation-api-3.0.2.jar.sha1
-rw-r--r-- 1 root root 748810 Oct 13 07:32 bval-jsr-3.0.2.jar
-rw-r--r-- 1 root root 41 Oct 13 07:32 bval-jsr-3.0.2.jar.sha1
5.2 sha1 完整性校验
Maven Central 为 BVal 提供 .sha1(实测 .sha512 不存在,请求返回 404):
cd /opt/bval-manual/lib && cat bval-jsr-3.0.2.jar.sha1
回显(实测):
111d95c4f7c52f2a54dcb65bb0843e0026979ae6
Central 的 .sha1 是裸哈希(不含文件名),直接 sha1sum -c 会因格式不符而失败(实测):
cd /opt/bval-manual/lib && sha1sum -c bval-jsr-3.0.2.jar.sha1; echo "exit=$?"
回显(实测):
sha1sum: bval-jsr-3.0.2.jar.sha1: no properly formatted SHA1 checksum lines found
exit=1
正确的校验方式是先拼出「哈希 + 文件名」标准行再交给 sha1sum -c:
cd /opt/bval-manual/lib && printf '%s %s\n' "$(cat bval-jsr-3.0.2.jar.sha1)" bval-jsr-3.0.2.jar | sha1sum -c - && printf '%s %s\n' "$(cat jakarta.validation-api-3.0.2.jar.sha1)" jakarta.validation-api-3.0.2.jar | sha1sum -c -
回显(实测):
bval-jsr-3.0.2.jar: OK
jakarta.validation-api-3.0.2.jar: OK
两行 OK 说明两个 jar 均与 Central 官方哈希一致,校验通过;若输出 FAILED 说明下载不完整或被链路改写,删除重下。
5.3 javac/java -cp 直接编译运行
复用 4.5 节的源码(去掉 package demo; 行后按默认包编译,或保留 package 并建对应目录),实测保留 package:
mkdir -p /opt/bval-manual/src/demo /opt/bval-manual/classes && sed 's/^package demo;/package demo;/' /opt/bval-demo/src/main/java/demo/BvalDemo.java > /opt/bval-manual/src/demo/BvalDemo.java && javac -encoding UTF-8 -cp /opt/bval-manual/lib/jakarta.validation-api-3.0.2.jar -d /opt/bval-manual/classes /opt/bval-manual/src/demo/BvalDemo.java && java -Dfile.encoding=UTF-8 -cp "/opt/bval-manual/classes:/opt/bval-manual/lib/bval-jsr-3.0.2.jar:/opt/bval-manual/lib/jakarta.validation-api-3.0.2.jar" demo.BvalDemo | head -3
回显(实测首行):
ValidatorFactory 实现类: org.apache.bval.jsr.ApacheValidatorFactory
非法对象约束违反数: 4
注意 javac 只需要验证 API jar(注解与接口都在规范包里),运行时才需要 bval-jsr 实现 jar,两 jar 与方案 A 的最小 classpath 完全一致,方案 B 验证通过。
5.4 核对 jar 版本清单
BVal 主 jar 自带 Main-Class: org.apache.bval.util.BValVersion,可直接查看版本:
java -jar /opt/bval-manual/lib/bval-jsr-3.0.2.jar
回显(实测):
Project: Apache BVal
Version: 3.0.2
Revision: unknown
os.name: Linux
os.version: 6.8.0-138-generic
cd /tmp && jar xf /opt/bval-manual/lib/bval-jsr-3.0.2.jar META-INF/MANIFEST.MF && grep -E "Specification-|Implementation-Version" META-INF/MANIFEST.MF
回显(实测):
Specification-Title: Jakarta Bean Validation
Specification-Version: 3.0
Implementation-Title: Apache BVal :: Implementation
Implementation-Version: 3.0.2
MANIFEST 确认实现 3.0.2 版 Jakarta Bean Validation 3.0 规范,同时其 Build-Jdk-Spec: 11 说明运行底线为 Java 11,与 4.3 节选型表一致。
5.5 SPI 服务文件对照(3.0.x 与 2.0.x)
确认自动发现的机制差异:
unzip -p /opt/bval-manual/lib/bval-jsr-3.0.2.jar META-INF/services/jakarta.validation.spi.ValidationProvider 2>/dev/null || jar xf /opt/bval-manual/lib/bval-jsr-3.0.2.jar META-INF/services/jakarta.validation.spi.ValidationProvider && cat META-INF/services/jakarta.validation.spi.ValidationProvider
回显(实测):
org.apache.bval.jsr.ApacheValidationProvider
而 2.0.6(javax 时代)的服务文件名为 META-INF/services/javax.validation.spi.ValidationProvider(实测 jar tf 确认)。这是「jakarta 与 javax 不互通」的机制根源:两代 Provider 的 SPI 注册路径与 API 包名都不同。
六、方案对比与选择建议
| 维度 | 方案 A:Maven 依赖 | 方案 B:Central 手动双 jar |
|---|---|---|
| 依赖来源 | Maven 中央仓库(自动) | repo1.maven.org(手动 wget) |
| 所需 jar | bval-jsr + bval-extras + jakarta.validation-api | bval-jsr + jakarta.validation-api(最小) |
| 是否需联网 | 需(首次拉取依赖) | 需下载一次,之后可离线分发 |
| 版本管理 | 改 pom.xml 版本号即可 | 手动下载对应版本、自行管理目录 |
| 完整性校验 | Maven 仓库校验机制 | .sha1 手动比对(无 .sha512,实测) |
| 附带产物 | 仅 jar 与 pom | 同左(无 bin 发行包) |
| 适用场景 | 常规 Maven/Gradle 工程 | 无构建工具的服务器、离线内网 |
关键差异与选型建议:工程内使用一律选方案 A,版本升级只改版本号;临时验证、离线机器用方案 B。需要 bval-extras 扩展约束(银行卡号、IBAN、IP 等)时必须走方案 A(或方案 B 多下载一个 bval-extras-3.0.2.jar,约 42 KB)。
七、多版本管理与升级、降级
7.1 Maven 方式的多版本共存
Maven 本地仓库按「groupId/artifactId/version」目录存放,多版本天然共存。实测拉取 javax 时代的 2.0.6:
cd /opt/bval-demo && mvn -q dependency:get -Dartifact=org.apache.bval:bval-jsr:2.0.6 && ls /root/.m2/repository/org/apache/bval/bval-jsr/
回显(实测):
2.0.6
3.0.2
升级或降级只需修改 pom.xml 中 bval-jsr 的 version(如 3.0.2 改 2.0.6),同时必须把 jakarta.validation-api 换成 javax.validation:validation-api:2.0.1.Final,并把代码 import 从 jakarta.validation.* 改回 javax.validation.*,重新 mvn compile 即生效。
7.2 手动方式的多版本共存
历史版本的 jar 从 Central 按版本号路径下载(如 .../bval-jsr/2.0.6/bval-jsr-2.0.6.jar);源码发行包从官方下载站获取(实测确认可用版本为 0.5 / 1.1.2 / 2.0.6):
curl -sI https://downloads.apache.org/bval/2.0.6/bval-parent-2.0.6-source-release.zip | head -1
回显(实测):
HTTP/1.1 200 OK
不同版本 jar 放不同目录,运行时 -cp 指定其一;类路径上只保留一个 BVal 版本,避免 Provider 冲突。
7.3 多 JDK 共存与切换
本机同时存在 OpenJDK 8 与 17:
ls /usr/lib/jvm/ | grep -E "^java-(1\.8|17)"
回显(实测):
java-1.8.0
java-17
切换 java 命令默认指向用 alternatives --set java java-17-openjdk.x86_64(见 4.2 节);切换 Maven 使用的 JDK 则必须改 JAVA_HOME。BVal 3.0.2 在 Java 11 及以上均可运行(Build-Jdk-Spec: 11),切换后建议重跑 4.5 节 BvalDemo 做回归验证。
八、常见问题(FAQ)
Q1:mvn compile 报 invalid target release: 17 怎么办?
现象:pom 里 maven.compiler.target 是 17,编译报 Fatal error compiling: invalid target release: 17。原因:Maven 通过 JAVA_HOME 找编译用 JDK,而 CentOS 8 默认 JAVA_HOME 指向预装的 Java 8(实测 mvn -version 显示 Java version: 1.8.0_312)。解决:export JAVA_HOME=/usr/lib/jvm/java-17-openjdk 后重新编译;永久生效写 /etc/profile.d/java17.sh(完整命令见 4.2 节)。注意 alternatives --set java 只改 java 命令,不改 Maven 的行为。
Q2:程序里的中文输出变成 ?(问号)怎么办?
现象:校验消息里的中文打印为问号。这是 locale 未配置为 UTF-8(Maven platform encoding: ANSI_X3.4-1968 即此症状)。解决:运行前 export LANG=C.UTF-8,并在 java 命令加 -Dfile.encoding=UTF-8(本文所有回显均在此设置下采集);编译侧由 pom 的 project.build.sourceEncoding=UTF-8 保证。
Q3:报 NoClassDefFoundError: javax/validation/Validation(或反向 jakarta 找不到)怎么办?
典型的命名空间混用:BVal 3.0.x 只认 jakarta.validation.*,BVal 2.0.x 只认 javax.validation.*。排查两步:第一,确认 pom 中 bval-jsr 版本与 import 的包名是否匹配;第二,mvn dependency:tree | grep validation 检查是否同时存在 javax.validation:validation-api 与 jakarta.validation:jakarta.validation-api,只保留与 BVal 版本匹配的那个。
Q4:Maven 拉取依赖很慢或超时怎么办? 先确认 Central 可达:
curl -sI https://repo1.maven.org/maven2/org/apache/bval/bval-jsr/3.0.2/bval-jsr-3.0.2.jar | head -1
回显(实测):
HTTP/2 200
返回 200 说明链路正常,慢多为带宽问题,可重试或改用国内镜像(编辑 ~/.m2/settings.xml 的 <mirrors> 段添加阿里云 https://maven.aliyun.com/repository/public,<mirrorOf> 取 central)。离线机器直接改走方案 B。
Q5:Validation.buildDefaultValidatorFactory() 报 ValidationException: No validator provider found?
说明 classpath 上没有 BVal 实现 jar。检查运行 classpath 是否包含 bval-jsr-3.0.2.jar(只有 jakarta.validation-api 时 SPI 文件不存在,找不到 Provider)。方案 B 下注意 -cp 两个 jar 都要带上(见 5.3 节)。
Q6:sha1 校验失败怎么处理?
sha1sum 输出与 .sha1 文件内容不一致说明下载不完整或被中间链路改写:删除坏文件重新 wget;若反复失败,检查代理是否改写二进制。校验通过前不要使用该 jar。
九、卸载与清理
按「工程 → 本地仓库 → 系统包」顺序清理。
删除实验工程与手动安装目录:
rm -rf /opt/bval-demo /opt/bval-manual
回显(实测,无输出即成功):
清理 Maven 本地仓库中的 BVal 与验证 API 缓存:
rm -rf /root/.m2/repository/org/apache/bval /root/.m2/repository/jakarta/validation && ls /root/.m2/repository/org/apache/bval
回显(实测):
ls: cannot access '/root/.m2/repository/org/apache/bval': No such file or directory
卸载系统级 Maven 与 JDK 17:
dnf remove -y maven java-17-openjdk-devel java-17-openjdk java-17-openjdk-headless
输出节选(实测,Removed 列表很长,仅列本文关心的条目):
Removed:
java-17-openjdk-1:17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-devel-1:17.0.1.0.12-2.el8_5.x86_64
java-17-openjdk-headless-1:17.0.1.0.12-2.el8_5.x86_64
java-1.8.0-openjdk-1:1.8.0.312.b07-2.el8_5.x86_64
java-1.8.0-openjdk-devel-1:1.8.0.312.b07-2.el8_5.x86_64
java-1.8.0-openjdk-headless-1:1.8.0.312.b07-2.el8_5.x86_64
maven-1:3.5.4-5.module_el8.0.0+39+6a9b6e22.noarch
maven-lib-1:3.5.4-5.module_el8.0.0+39+6a9b6e22.noarch
Complete!
注意实测坑:卸载 java-17 时 dnf 会连带卸载预装的 Java 8(alternatives 家族依赖闭包把两个 JDK 绑在同一事务里),并非「卸 17 留 8」;若必须保留 Java 8,应在卸载后执行 dnf install -y java-1.8.0-openjdk 装回。
删除 4.2 节的环境变量文件并验证:
rm -f /etc/profile.d/java17.sh && java -version 2>&1; mvn -version 2>&1
回显(实测):
bash: java: command not found
bash: mvn: command not found
两条命令均报 command not found,卸载完成(如需继续用 Java 8,按上文 dnf install -y java-1.8.0-openjdk 装回即可)。
十、参考链接
- Apache BVal 项目主页:https://bval.apache.org/
- Maven 中央仓库 bval-jsr:https://repo1.maven.org/maven2/org/apache/bval/bval-jsr/
- Maven 中央仓库 jakarta.validation-api:https://repo1.maven.org/maven2/jakarta/validation/jakarta.validation-api/
- Apache BVal 官方下载(仅源码发行包):https://downloads.apache.org/bval/
- Jakarta Bean Validation 规范:https://jakarta.ee/specifications/bean-validation/3.0/