Ubuntu 22.04 安装 Apache Commons BeanUtils 指南
在 Ubuntu 22.04 从零安装 Commons BeanUtils 1.11.0:apt 装 OpenJDK 17 与 Maven,Maven 依赖与发行包双方案,含 sha512 校验、依赖补齐、最小验证与卸载,全部命令实测。
Ubuntu 22.04 安装 Apache Commons BeanUtils 指南
目标:在 Ubuntu 22.04 服务器上从零搭建可编译、可运行 Apache Commons BeanUtils 的 Java 环境,覆盖「Maven 依赖」与「官方发行包手动安装」两种方案、sha512 完整性校验、运行期依赖补齐、最小验证代码、多版本管理与卸载,已在 Ubuntu 22.04(OpenJDK 17.0.20.1、Maven 3.6.3)实测通过。
一、环境信息
本篇所有命令与回显均在以下环境中实测采集,复现时请保持相近版本:
- 操作系统:Ubuntu 22.04.5 LTS(jammy),x86_64,内核 6.8.0-138-generic
- JDK:OpenJDK 17.0.20.1(
openjdk-17-jdk,apt 官方仓库,另备 OpenJDK 11.0.32.1 供多版本切换) - 构建工具:Apache Maven 3.6.3(
maven,apt 官方仓库) - 组件版本:Apache Commons BeanUtils 1.11.0(downloads.apache.org 当前稳定线最新版,2026-10 实测)
- 实验目录:
/opt/lab/beanutils(方案 A 工程proj,方案 B 目录manual,发行包目录dist) - 执行用户:root
二、版本选型
Commons BeanUtils 的发布版以 Java Bean 属性反射工具为核心,选型先确认版本线与 JDK 要求:
| 版本 | 发布状态 | 对 JDK 要求 | 运行期依赖 | 获取渠道 |
|---|---|---|---|---|
| 1.11.0 | 稳定版(本篇实测采用) | Java 8 及以上 | commons-logging 1.3.5、commons-collections 3.2.2 | downloads.apache.org 与 Maven 中央仓库 |
| 2.0.0-M2 | 里程碑预览(新坐标 commons-beanutils2) | 以官方发布说明为准 | 以其发行包内说明为准 | downloads.apache.org 的 binaries 目录 |
逐项说明:
- 1.11.0:
downloads.apache.org/commons/beanutils/目录下当前唯一的 1.x 稳定版,与 Maven 中央仓库<latest>1.11.0</latest>一致;实测其字节码major version: 52(即 Java 8 编译),可在 Java 8/11/17 运行。 - 2.0.0-M2:属于新一代
commons-beanutils2坐标的里程碑预览,坐标与 1.x 不同,生产环境暂不建议,本篇不展开。 - 选型结论:以 1.11.0 为准,下文全部实测均基于该版本。
验证中央仓库最新版与本仓库字节码版本:
# curl -s --max-time 20 "https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/maven-metadata.xml" | grep -E 'latest|release'
<latest>1.11.0</latest>
<release>1.11.0</release>
# javap -v -cp dist/commons-beanutils-1.11.0/commons-beanutils-1.11.0.jar org.apache.commons.beanutils.BeanUtils 2>/dev/null | grep -m1 major
major version: 52
major version: 52 说明该库按 Java 8 字节码发布,对 JDK 11、17 向下兼容,本篇环境选 JDK 17 无兼容问题。
三、安装 JDK 与 Maven
3.1 更新软件源索引
先刷新 apt 索引,保证后续安装能命中最新可用包:
# apt-get update | tail -3
Hit:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
Hit:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
Reading package lists...
回显末尾出现 Reading package lists 且无报错行,说明索引刷新完成。
3.2 安装 JDK、Maven 与下载工具
一条命令装齐 JDK 17 与 Maven:
# apt-get install -y openjdk-17-jdk maven
maven is already the newest version (3.6.3-5).
openjdk-17-jdk is already the newest version (17.0.20.1+1-1~22.04).
本次实测基线已带 JDK 17 与 Maven,因此回显为 already the newest version;curl、wget 在本机基线缺失,是实际新装的,真实安装回显如下:
# apt-get install -y curl wget
Setting up libcurl4:amd64 (7.81.0-1ubuntu1.29) ...
Setting up curl (7.81.0-1ubuntu1.29) ...
两种回显都正常:前者说明包已在系统内,后者是真实解包安装过程,只要命令退出码为 0 即可。
3.3 验证安装
分别验证编译器、运行时与构建工具:
# java -version
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
# javac -version
javac 17.0.20.1
# mvn -v
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 17.0.20.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "6.8.0-138-generic", arch: "amd64", family: "unix"
注意 platform encoding: ANSI_X3.4-1968,说明当前 shell 未启用 UTF-8 locale,直接输出中文会变问号,解法见 3.4 与 FAQ Q2。
3.4 多版本管理(可选)
基线同时装有 OpenJDK 11,用 update-alternatives 管理切换:
# update-alternatives --list java
/usr/lib/jvm/java-11-openjdk-amd64/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java
切到 Java 11 并验证,再切回 17:
# update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/bin/java to provide /usr/bin/java (java) in manual mode
# java -version | head -1
openjdk version "11.0.32.1" 2026-08-18
# update-alternatives --set java /usr/lib/jvm/java-17-openjdk-amd64/bin/java
update-alternatives: using /usr/lib/jvm/java-17-openjdk-amd64/bin/java to provide /usr/bin/java (java) in manual mode
# java -version | head -1
openjdk version "17.0.20.1" 2026-08-18
Commons BeanUtils 1.11.0 是 Java 8 字节码,11 与 17 都能运行;日常建议默认 17,需要验证老环境兼容性时再临时切 11。
四、方案 A:Maven 依赖接入
Maven 方案由中央仓库自动拉取主 jar 与全部运行期依赖,是首选接入方式。
4.1 创建工程骨架
创建目录并准备 pom.xml:
# mkdir -p /opt/lab/beanutils/proj/src/main/java/com/example/beanutils
# cd /opt/lab/beanutils/proj
pom.xml 全文如下:
<?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>com.example</groupId>
<artifactId>beanutils-lab</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>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.11.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins>
</build>
</project>
逐项说明:
maven.compiler.source/target设为 17,与已装 JDK 匹配;project.build.sourceEncoding设 UTF-8,避免中文源码乱码。- 唯一业务依赖
commons-beanutils:1.11.0,其余两个插件显式固定版本:实测发现不固定版本时,Maven 会解析到很旧的编译插件(见 FAQ Q3)。 exec-maven-plugin用于第 4.3 步与后续示例的直接运行。
把示例源码放入 src/main/java/com/example/beanutils/(最小验证代码见第七章),目录结构核对:
# find /opt/lab/beanutils/proj -type f | sort
/opt/lab/beanutils/proj/pom.xml
/opt/lab/beanutils/proj/src/main/java/com/example/beanutils/ConverterDemo.java
/opt/lab/beanutils/proj/src/main/java/com/example/beanutils/CopyDemo.java
/opt/lab/beanutils/proj/src/main/java/com/example/beanutils/DynaBeanDemo.java
/opt/lab/beanutils/proj/src/main/java/com/example/beanutils/MapBeanDemo.java
/opt/lab/beanutils/proj/src/main/java/com/example/beanutils/Model.java
/opt/lab/beanutils/proj/src/main/java/com/example/beanutils/NestedDemo.java
4.2 核查依赖树
# mvn dependency:tree 2>&1 | sed -n '/maven-dependency-plugin/,/BUILD SUCCESS/p' | head -9
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ beanutils-lab ---
[INFO] com.example:beanutils-lab:jar:1.0.0
[INFO] \- commons-beanutils:commons-beanutils:jar:1.11.0:compile
[INFO] +- commons-logging:commons-logging:jar:1.3.5:compile
[INFO] \- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
依赖树与官方 pom 声明一致:commons-beanutils 1.11.0 下挂 commons-logging 1.3.5 与 commons-collections 3.2.2 两个 compile 依赖。这正是方案 B 手动安装时必须一并放入 classpath 的两个 jar。
4.3 编译
# mvn -q compile
# ls target/classes/com/example/beanutils/
ConverterDemo$Form.class
ConverterDemo.class
CopyDemo$Form.class
CopyDemo.class
DynaBeanDemo.class
MapBeanDemo.class
Model$Dept.class
Model$Employee.class
Model$Manager.class
Model.class
NestedDemo.class
mvn -q 静默模式编译成功时无输出,退出码 0;target/classes 下出现全部字节码文件即编译完成。
五、方案 B:官方发行包手动接入
适合无法使用 Maven 的环境:从官方站取发行包,自行补齐依赖后用 javac/java -cp 直跑。
5.1 下载发行包并校验
# mkdir -p /opt/lab/beanutils/dist && cd /opt/lab/beanutils/dist
# curl -sSO https://downloads.apache.org/commons/beanutils/binaries/commons-beanutils-1.11.0-bin.tar.gz
# curl -sSO https://downloads.apache.org/commons/beanutils/binaries/commons-beanutils-1.11.0-bin.tar.gz.sha512
# cat commons-beanutils-1.11.0-bin.tar.gz.sha512
c1c0e71f526db64fc7aa9934f2910eedea5e575909edb3de39566e9a27b300e28826f6997b23338ef93dfee34d220077ba8669459640bddf5619ca0bb740d8ba
# sha512sum commons-beanutils-1.11.0-bin.tar.gz
c1c0e71f526db64fc7aa9934f2910eedea5e575909edb3de39566e9a27b300e28826f6997b23338ef93dfee34d220077ba8669459640bddf5619ca0bb740d8ba commons-beanutils-1.11.0-bin.tar.gz
sha512sum 输出与官方 .sha512 文件逐字一致,完整性校验通过。
5.2 解包与内容清点
# tar -xzf commons-beanutils-1.11.0-bin.tar.gz
# ls -l commons-beanutils-1.11.0/
total 2724
-rw-r--r-- 1 root root 11359 May 25 2025 LICENSE.txt
-rw-r--r-- 1 root root 179 May 25 2025 NOTICE.txt
-rw-r--r-- 1 root root 21837 May 25 2025 RELEASE-NOTES.txt
drwxr-xr-x 7 root root 4096 May 25 2025 apidocs
-rw-r--r-- 1 root root 1449634 May 25 2025 commons-beanutils-1.11.0-javadoc.jar
-rw-r--r-- 1 root root 303875 May 25 2025 commons-beanutils-1.11.0-sources.jar
-rw-r--r-- 1 root root 298782 May 25 2025 commons-beanutils-1.11.0-test-sources.jar
-rw-r--r-- 1 root root 435374 May 25 2025 commons-beanutils-1.11.0-tests.jar
-rw-r--r-- 1 root root 246806 May 25 2025 commons-beanutils-1.11.0.jar
关键观察:1.11.0 发行包内只有主 jar 与 javadoc/sources/tests 附属包,没有 lib/ 目录,运行期依赖需要另行下载,这就是 5.3 存在的原因。
5.3 从中央仓库补齐运行期依赖
按 4.2 依赖树的版本号取两个依赖 jar:
# mkdir -p /opt/lab/beanutils/manual/lib && cd /opt/lab/beanutils/manual
# cp /opt/lab/beanutils/dist/commons-beanutils-1.11.0/commons-beanutils-1.11.0.jar lib/
# curl -sSO https://repo.maven.apache.org/maven2/commons-logging/commons-logging/1.3.5/commons-logging-1.3.5.jar
# curl -sSO https://repo.maven.apache.org/maven2/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar
# mv commons-logging-1.3.5.jar commons-collections-3.2.2.jar lib/
# ls -l lib/
total 896
-rw-r--r-- 1 root root 246806 commons-beanutils-1.11.0.jar
-rw-r--r-- 1 root root 588337 commons-collections-3.2.2.jar
-rw-r--r-- 1 root root 73737 commons-logging-1.3.5.jar
三个 jar 齐备:主 jar 246806 字节、collections 588337 字节、logging 73737 字节。
5.4 编译与运行
把示例源码复制过来编译(源码与方案 A 相同,-encoding UTF-8 必须带上):
# cp -r /opt/lab/beanutils/proj/src .
# javac -encoding UTF-8 -cp lib/commons-beanutils-1.11.0.jar -d out $(find src -name "*.java")
# ls out/com/example/beanutils/ | head -3
ConverterDemo$Form.class
ConverterDemo.class
CopyDemo.class
先做一个反例:classpath 只给主 jar,运行即报依赖缺失:
# java -cp out:lib/commons-beanutils-1.11.0.jar com.example.beanutils.NestedDemo
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.apache.commons.beanutils.ConvertUtilsBean.<init>(ConvertUtilsBean.java:154)
at org.apache.commons.beanutils.BeanUtilsBean.<init>(BeanUtilsBean.java:113)
at org.apache.commons.beanutils.BeanUtilsBean$1.initialValue(BeanUtilsBean.java:55)
这是手动安装最常见的坑:BeanUtils 初始化时就要用 commons-logging。补齐后运行:
# java -cp out:lib/commons-beanutils-1.11.0.jar:lib/commons-logging-1.3.5.jar:lib/commons-collections-3.2.2.jar com.example.beanutils.NestedDemo
读 dept.deptName = null
读 dept.manager.name = null
写后读 dept.deptName = 平台架构部
写后读 dept.manager.title = 高级经理
整对象核对 = 李四 @ 平台架构部
输出正常,方案 B 接入完成。中文输出依赖 UTF-8 locale,若出现问号见 FAQ Q2。
六、方案对比与选型建议
| 维度 | 方案 A:Maven 依赖 | 方案 B:发行包手动安装 |
|---|---|---|
| 依赖管理 | 自动拉取 logging/collections 两个传递依赖 | 必须按依赖树手动补齐三个 jar |
| 版本升级 | 改 pom 版本号重新构建即可 | 重新下载发行包并核对 sha512 |
| 适用场景 | 常规工程、CI 流水线 | 无外网构建机、只读运维环境 |
| 出错概率 | 低(依赖树可核查) | 高(漏 jar 直接 NoClassDefFoundError) |
| 离线友好 | 需预置本地仓库 | 天然离线 |
选型建议:优先方案 A,依赖树一行命令即可核查;只有目标机器完全无法使用 Maven 时选方案 B,且务必同时放主 jar、commons-logging、commons-collections 三个 jar。
七、最小验证
无论哪种方案,用同一段「嵌套属性读写」代码验证安装是否可用。NestedDemo.java 全文:
package com.example.beanutils;
import org.apache.commons.beanutils.PropertyUtils;
/** 示例:PropertyUtils 跨层级嵌套属性读写 */
public class NestedDemo {
public static void main(String[] args) throws Exception {
Model.Employee emp = new Model.Employee();
emp.setEmpName("张三");
emp.setAge(30);
String deptName = (String) PropertyUtils.getProperty(emp, "dept.deptName");
String mgrName = (String) PropertyUtils.getProperty(emp, "dept.manager.name");
System.out.println("读 dept.deptName = " + deptName);
System.out.println("读 dept.manager.name = " + mgrName);
PropertyUtils.setProperty(emp, "dept.deptName", "平台架构部");
PropertyUtils.setProperty(emp, "dept.manager.name", "李四");
PropertyUtils.setProperty(emp, "dept.manager.title", "高级经理");
System.out.println("写后读 dept.deptName = " + PropertyUtils.getProperty(emp, "dept.deptName"));
System.out.println("写后读 dept.manager.title = " + PropertyUtils.getProperty(emp, "dept.manager.title"));
System.out.println("整对象核对 = " + emp.getDept().getManager().getName() + " @ " + emp.getDept().getDeptName());
}
}
Maven 方案直接运行:
# cd /opt/lab/beanutils/proj
# mvn -q compile exec:java -Dexec.mainClass=com.example.beanutils.NestedDemo
读 dept.deptName = null
读 dept.manager.name = null
写后读 dept.deptName = 平台架构部
写后读 dept.manager.title = 高级经理
整对象核对 = 李四 @ 平台架构部
初始为空的嵌套字段读出 null 不抛异常;写入后逐层 setter 被正确调用,三条核对输出与预期一致,安装验证通过。
八、FAQ
Q1:运行时报 NoClassDefFoundError: org/apache/commons/logging/LogFactory 怎么办?
这是手动安装时 classpath 缺 commons-logging 导致。实测复现与解法:把 commons-logging-1.3.5.jar 与 commons-collections-3.2.2.jar 一并加入 -cp,即 5.4 的三个 jar 写法;Maven 方案则由依赖树自动带上,无此问题。
Q2:程序里输出的中文变成了问号?
本机默认 locale 是 POSIX(mvn -v 显示 platform encoding: ANSI_X3.4-1968),JVM 按 ASCII 编码输出。实测在执行命令前加 export LANG=C.UTF-8,JVM 即按 UTF-8 输出,中文恢复正常;编译源码时同时保留 -encoding UTF-8(Maven 已由 project.build.sourceEncoding 覆盖)。
Q3:不固定插件版本时 Maven 用了很旧的编译插件?
实测在未显式声明版本的工程里,首次构建报错信息中出现 maven-compiler-plugin:3.1:compile,该老插件对高版本 JDK 支持差。解法是在 pom 的 <build><plugins> 中显式固定 maven-compiler-plugin 3.11.0(见 4.1),构建行为在 Maven 3.6.3 上稳定可复现。
Q4:1.11.0 与 2.0.0-M2 该选哪个?
生产选 1.11.0:它与 1.x 全系 API 兼容、Maven 坐标 commons-beanutils:commons-beanutils 不变。2.0.0-M2 属于新坐标 commons-beanutils2 的里程碑预览,包名与坐标都会变,仅适合前瞻性验证,不要引入生产依赖。
九、卸载
按接入方式分别清理。方案 A 的工程与本地仓库缓存:
# rm -rf /opt/lab/beanutils/proj
# rm -rf ~/.m2/repository/commons-beanutils
方案 B 的发行包与依赖目录:
# rm -rf /opt/lab/beanutils/dist /opt/lab/beanutils/manual
卸载工具链本身(先 Maven 后 JDK,并验证卸载结果):
# apt-get purge -y maven
Removing maven (3.6.3-5) ...
Purging configuration files for maven (3.6.3-5) ...
# mvn -v
bash: line 1: mvn: command not found
# apt-get purge -y openjdk-17-jdk openjdk-17-jre
Removing openjdk-17-jdk:amd64 (17.0.20.1+1-1~22.04) ...
Removing openjdk-17-jre:amd64 (17.0.20.1+1-1~22.04) ...
mvn -v 报 command not found 证明卸载生效。若还需恢复环境,反向安装即可:
# apt-get install -y openjdk-17-jdk maven
恢复后实测 java -version 回到 17.0.20.1、mvn -v 回到 Apache Maven 3.6.3。
十、参考链接
- Apache Commons BeanUtils 官方主页:https://commons.apache.org/proper/commons-beanutils/
- 官方下载目录(binaries 与 sha512):https://downloads.apache.org/commons/beanutils/
- Maven 中央仓库坐标页:https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/
- 官方用户指南:https://commons.apache.org/proper/commons-beanutils/userguide.html
- Apache Maven 官方文档:https://maven.apache.org/guides/