Apache Commons BeanUtils 常用 CLI 命令与工具详解
Commons BeanUtils 无自带命令行工具,本篇实测其命令链路:Maven 的 compile、exec:java、dependency:tree,JDK 的 jar、javap、java -cp,及发行包校验解包,附报错排查。
Apache Commons BeanUtils 常用 CLI 命令与工具详解
目标:Commons BeanUtils 是纯 Java 库,本身不提供任何命令行可执行程序,本篇实测整理围绕它展开日常工作的完整命令链路——Maven 工具链(compile、exec:java、dependency:tree)、JDK 自带工具(jar、javap、java -cp)与发行包处理命令(curl、sha512sum、tar),全部命令在 Ubuntu 22.04(OpenJDK 17.0.20.1、Maven 3.6.3)与 CentOS Linux 8(OpenJDK 17.0.1、Maven 3.10.0)实测通过。
一、环境信息
本篇所有命令与回显均在以下环境实测采集:
- 操作系统:Ubuntu 22.04.5 LTS(x86_64,内核 6.8.0-138-generic)为主,CentOS Linux 8 做交叉验证
- JDK:OpenJDK 17.0.20.1(Ubuntu)/ OpenJDK 17.0.1(CentOS 8)
- 构建工具:Apache Maven 3.6.3(Ubuntu)/ Apache Maven 3.10.0(CentOS 8)
- 组件版本:Apache Commons BeanUtils 1.11.0 及其依赖 commons-logging 1.3.5、commons-collections 3.2.2
- 实验目录:
/opt/lab/beanutils(Maven 工程proj、手动目录manual、发行包目录dist) - 执行用户:root
命令分三组:Maven 工具链负责依赖与构建执行;JDK 自带工具负责字节码观察与手动运行;发行包命令负责获取与校验。三组命令可独立使用,也可串成完整工作流。
二、Maven 工具链命令
2.1 环境自检:mvn -v
# 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"
重点看两行:Java version 确认 Maven 用的 JDK 与预期一致;platform encoding: ANSI_X3.4-1968 提示未启用 UTF-8 locale,运行含中文输出的示例前先 export LANG=C.UTF-8。
2.2 编译:mvn compile
# cd /opt/lab/beanutils/proj
# mvn -q compile
# echo $?
0
-q 静默模式下编译成功无输出,用退出码 0 确认;产物落在 target/classes。去掉 -q 可看到 [INFO] BUILD SUCCESS 的完整过程日志。
2.3 直接运行示例:mvn exec:java
# export LANG=C.UTF-8
# mvn -q compile exec:java -Dexec.mainClass=com.example.beanutils.NestedDemo
读 dept.deptName = null
读 dept.manager.name = null
写后读 dept.deptName = 平台架构部
写后读 dept.manager.title = 高级经理
整对象核对 = 李四 @ 平台架构部
五个示例类的运行命令汇总(回显详见第五篇快速入门,此处不重复):
# mvn -q compile exec:java -Dexec.mainClass=com.example.beanutils.CopyDemo
# mvn -q compile exec:java -Dexec.mainClass=com.example.beanutils.ConverterDemo
# mvn -q compile exec:java -Dexec.mainClass=com.example.beanutils.DynaBeanDemo
# mvn -q compile exec:java -Dexec.mainClass=com.example.beanutils.MapBeanDemo
-Dexec.mainClass 传完整类名;工程已固定 exec-maven-plugin 3.1.0,无需额外写 <mainClass> 配置即可逐类运行。
2.4 依赖核查:mvn dependency:tree
# 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
这条命令是手动安装(方案 B)的「依赖清单生成器」:树里出现的每个坐标都要在 -cp 里给到对应 jar。
三、JDK 自带工具命令
3.1 查看 jar 内容:jar tf
# jar tf dist/commons-beanutils-1.11.0/commons-beanutils-1.11.0.jar | head -6
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/commons/
org/apache/commons/beanutils/
# jar tf dist/commons-beanutils-1.11.0/commons-beanutils-1.11.0.jar | grep -c "\.class$"
135
主 jar 内共 135 个 class 文件,包根为 org/apache/commons/beanutils。排查「类是否存在」「包名是否正确」时用它最快。
3.2 反汇编 API 签名:javap
# javap -cp dist/commons-beanutils-1.11.0/commons-beanutils-1.11.0.jar org.apache.commons.beanutils.BeanUtils | head -12
Compiled from "BeanUtils.java"
public class org.apache.commons.beanutils.BeanUtils {
public static java.lang.Object cloneBean(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException, java.lang.NoSuchMethodException;
public static void copyProperties(java.lang.Object, java.lang.Object) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException;
public static void copyProperty(java.lang.Object, java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException;
public static <K, V> java.util.Map<K, V> createCache();
public static java.util.Map<java.lang.String, java.lang.String> describe(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException, java.lang.NoSuchMethodException;
public static java.lang.String[] getArrayProperty(java.lang.Object, java.lang.String) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException, java.lang.NoSuchMethodException;
public static boolean getCacheFast(java.util.Map<?, ?>);
public static int getDebug();
public static java.lang.String getIndexedProperty(java.lang.Object, java.lang.String) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException, java.lang.NoSuchMethodException;
public static java.lang.String getIndexedProperty(java.lang.Object, java.lang.String, int) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException, java.lang.NoSuchMethodException;
签名能直接回答参数顺序类疑问:copyProperties(java.lang.Object, java.lang.Object) 不带泛型名,需查官方文档确认首参为 dest;describe 返回 Map<String, String>,值全为字符串。javap -v 加 -v 还能看到 major version: 52 的字节码版本。
3.3 手动编译运行:javac 与 java -cp
编译(encoding 必须显式给 UTF-8):
# cd /opt/lab/beanutils/manual
# javac -encoding UTF-8 -cp lib/commons-beanutils-1.11.0.jar -d out $(find src -name "*.java")
缺依赖的反例(只放主 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)
三 jar 齐备的正确运行:
# 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 = 高级经理
整对象核对 = 李四 @ 平台架构部
-cp 用冒号分隔(Linux 惯例),顺序无关;缺哪个 jar 报哪个 NoClassDefFoundError,报错栈首行类名就是线索。
四、发行包处理命令
4.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
curl -sS -O 静默下载并保留远端文件名;-S 保证出错时仍打印错误。两段 sha512 逐字一致才算校验通过。
4.2 解包与清点
# tar -xzf commons-beanutils-1.11.0-bin.tar.gz
# tar -tzf commons-beanutils-1.11.0-bin.tar.gz | head -5
commons-beanutils-1.11.0/LICENSE.txt
commons-beanutils-1.11.0/NOTICE.txt
commons-beanutils-1.11.0/RELEASE-NOTES.txt
commons-beanutils-1.11.0/commons-beanutils-1.11.0-javadoc.jar
commons-beanutils-1.11.0/commons-beanutils-1.11.0-sources.jar
# ls -l commons-beanutils-1.11.0/ | head -6
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
tar -tzf 先列清单不解包,适合确认包内结构;1.11.0 发行包只有主 jar 与附属 jar,没有 lib/ 依赖目录,依赖需另取。
4.3 补依赖 jar
# cd /opt/lab/beanutils/manual
# 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
依赖 URL 的版本号以 2.4 依赖树输出为准,三个 jar 文件大小与实测一致即取材正确。
五、命令速查表
| 场景 | 命令 | 关键参数 |
|---|---|---|
| 构建工具自检 | mvn -v | 看 Java version 与 platform encoding |
| 编译工程 | mvn -q compile | -q 静默,退出码判成败 |
| 运行示例 | mvn -q compile exec:java -Dexec.mainClass=完整类名 | mainClass 传全限定名 |
| 依赖核查 | mvn dependency:tree | 树中坐标即 classpath 清单 |
| 看 jar 内容 | jar tf commons-beanutils-1.11.0.jar | 配 grep -c "\.class$" 数类 |
| 反汇编签名 | javap -cp commons-beanutils-1.11.0.jar 全限定类名 | -v 可看 major version |
| 手动编译 | javac -encoding UTF-8 -cp 主jar -d out $(find src -name "*.java") | encoding 必给 |
| 手动运行 | java -cp out:主jar:logging:collections 类名 | 冒号分隔 |
| 下载 | curl -sSO URL | -sS 静默留错 |
| 校验 | sha512sum 文件 | 与官方 .sha512 比对 |
| 解包/清单 | tar -xzf / tar -tzf | -z 处理 gz |
六、FAQ
Q1:exec:java 报找不到主类?
-Dexec.mainClass 必须是全限定名(含包名),并确认 mvn compile 已通过;类名大小写与文件名一致,如 com.example.beanutils.NestedDemo。
Q2:示例中文输出变问号?
系统默认 POSIX locale 所致,先 export LANG=C.UTF-8 再运行;手动 javac 时同时保留 -encoding UTF-8,两个环节缺一不可。
Q3:手动运行报 NoClassDefFoundError: org/apache/commons/logging/LogFactory?
classpath 缺依赖 jar。用 mvn dependency:tree 的输出核对三 jar(主 jar、commons-logging、commons-collections)是否全部就位,并确认 -cp 冒号分隔写法正确。
Q4:javap 报「找不到类」?
-cp 指向 jar 文件本身(不是目录),类名用全限定名。例如 javap -cp lib/commons-beanutils-1.11.0.jar org.apache.commons.beanutils.BeanUtils;jar 路径错了会当成目录找不到。
七、参考链接
- Apache Commons BeanUtils 官方主页:https://commons.apache.org/proper/commons-beanutils/
- 官方下载目录:https://downloads.apache.org/commons/beanutils/
- Maven 中央仓库坐标页:https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/
- Apache Maven 官方文档:https://maven.apache.org/guides/
- exec-maven-plugin 用法:https://www.mojohaus.org/exec-maven-plugin/