CentOS 8 安装 Apache BVal 指南

在 CentOS 8 从零安装 Apache BVal 3.0.2:vault 源、JDK 17 与 Maven 安装及 alternatives/JAVA_HOME 切换、Maven 依赖与手动双 jar 两方案、sha1 校验、多版本管理与卸载,全程实测。

Apache BValBVal2026/10/13

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.2jakarta.validation(Jakarta Bean Validation 3.0)Java 11+ 编译运行Maven 中央仓库本文采用,最新稳定版
BVal (bval-jsr)2.0.6javax.validation(Bean Validation 2.0)Java 8+Maven 中央仓库 / downloads.apache.org(仅源码包)存量 javax 工程常见
JDKOpenJDK 17.0.1(LTS)——CentOS 8 系统仓库 java-17-openjdk编译与运行示例均正常
Maven3.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)
所需 jarbval-jsr + bval-extras + jakarta.validation-apibval-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 装回即可)。

十、参考链接

  1. Apache BVal 项目主页:https://bval.apache.org/
  2. Maven 中央仓库 bval-jsr:https://repo1.maven.org/maven2/org/apache/bval/bval-jsr/
  3. Maven 中央仓库 jakarta.validation-api:https://repo1.maven.org/maven2/jakarta/validation/jakarta.validation-api/
  4. Apache BVal 官方下载(仅源码发行包):https://downloads.apache.org/bval/
  5. Jakarta Bean Validation 规范:https://jakarta.ee/specifications/bean-validation/3.0/