Apache Commons DBCP 常用 CLI 命令与工具详解
讲清 Apache Commons DBCP 2.14.0 的命令行可用形态:无独立 CLI 的验证依据、发行包类结构、java -cp 直跑自写池诊断程序、jshell 交互实操、Maven 常用命令,附连接数监控与池状态导出真实回显。
Apache Commons DBCP 常用 CLI 命令与工具详解
目标:搞清楚 Apache Commons DBCP 2.14.0 到底能怎么「在命令行用」——它没有任何自带 CLI,命令行能力的正确形态是 java -cp 直跑自写诊断程序、jshell 交互、以及 Maven 命令。全部命令与回显已在 Ubuntu 22.04 / CentOS 8(JDK 17)实测通过。
一、环境信息
本章先固定命令行实验环境。DBCP 是 jar 库、无常驻进程,与 tar、redis-cli 这类自带命令行工具的软件不同:它没有 dbcpctl 之类的可执行入口,所谓「CLI 用法」指的是围绕它的三类命令行操作。
java -version 2>&1 | head -1
mvn -v 2>&1 | head -1
实测回显(Ubuntu 22.04):
openjdk version "17.0.20.1" 2026-08-18
Apache Maven 3.6.3
实测回显(CentOS 8,需先设 JAVA_HOME,见《CentOS 8 安装 Apache Commons DBCP 指南》):
openjdk version "17.0.1" 2021-10-19 LTS
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
💡 技术拓展:Apache Commons DBCP 只是「数据库连接池」大家庭中的一员。Java 连接池复用物理数据库连接、降低握手与鉴权开销,业界常见实现对比:
| 连接池 | 出身 | 特点 | 适用场景 |
|---|---|---|---|
| Commons DBCP2 | Apache,本文主角 | 纯 Java、参数直观、与 Tomcat/Spring 兼容广 | 传统项目、需轻量显式配置 |
| HikariCP | 社区 | 极致性能、极少参数 | 高并发新项目首选 |
| C3P0 | 社区 | 老牌、配置项多 | 存量 Hibernate 项目 |
| Druid | 阿里 | 自带监控台、SQL 防火墙 | 国内运维监控要求高 |
| Tomcat JDBC Pool | Apache Tomcat | DBCP 的替代品、异步取连接 | Tomcat 应用内 |
要点:Druid 自带 Web 监控台、HikariCP 有 Micrometer 指标,而 DBCP 本身不带任何监控命令行或面板,池状态只能靠自己写的程序或 JMX 获取——这正是本文第五章「自写诊断工具」的存在意义。
二、工具概览
DBCP 的命令行相关工具分四类,后面各章逐一给出实测:
| 形态 | 用途 | 是否 DBCP 自带 |
|---|---|---|
| java -jar 发行包主 jar | 无入口,实测直接报错 | 不可用(见第四章) |
| java -cp 直跑自写程序 | 打印池状态、做连通性自检 | 商店里没有,需自写 |
| jshell 交互 | 临时探索 API、快速验证参数 | 需手动敲代码 |
| Maven 命令 | 依赖树核对、一键运行示例 | 需自写 pom |
三、前置条件
本章准备「可执行」的 jar 与依赖。命令行方式不依赖 Maven 运行时,但需要把主 jar 与三个传递依赖集齐。按第二章方案B 下载发行包与依赖:
sudo mkdir -p /opt/commons
cd /opt/commons
sudo curl -fsSLO https://downloads.apache.org/commons/dbcp/binaries/commons-dbcp2-2.14.0-bin.tar.gz
printf '%s %s\n' "$(curl -fsSL https://downloads.apache.org/commons/dbcp/binaries/commons-dbcp2-2.14.0-bin.tar.gz.sha512)" commons-dbcp2-2.14.0-bin.tar.gz | sha512sum -c -
sudo tar xzf commons-dbcp2-2.14.0-bin.tar.gz
cd commons-dbcp2-2.14.0 && sudo mkdir -p lib && cd lib
sudo curl -fsSLO https://repo1.maven.org/maven2/org/apache/commons/commons-pool2/2.13.0/commons-pool2-2.13.0.jar
sudo curl -fsSLO https://repo1.maven.org/maven2/commons-logging/commons-logging/1.3.5/commons-logging-1.3.5.jar
sudo curl -fsSLO https://repo1.maven.org/maven2/jakarta/transaction/jakarta.transaction-api/1.3.3/jakarta.transaction-api-1.3.3.jar
sudo curl -fsSLO https://repo1.maven.org/maven2/com/h2database/h2/2.5.252/h2-2.5.252.jar
ls -l
实测回显(校验一步与依赖清单):
commons-dbcp2-2.14.0-bin.tar.gz: OK
total 2880
-rw-r--r-- 1 root root 73737 Oct 13 16:32 commons-logging-1.3.5.jar
-rw-r--r-- 1 root root 156676 Oct 13 16:32 commons-pool2-2.13.0.jar
-rw-r--r-- 1 root root 2693360 Oct 13 16:32 h2-2.5.252.jar
-rw-r--r-- 1 root root 15392 Oct 13 16:32 jakarta.transaction-api-1.3.3.jar
四个 jar 缺一不可:缺 commons-pool2 报 org/apache/commons/pool2/impl/GenericObjectPool 找不到;缺 commons-logging 报 org/apache/commons/logging/LogFactory 找不到。
四、发行包结构:没有命令行入口
本章用实测证明 DBCP 不能像 tar 那样当命令用,并给出它真实的内部结构,供排查时参考。
4.1 java -jar 直接失败
cd /opt/commons/commons-dbcp2-2.14.0
java -jar commons-dbcp2-2.14.0.jar
echo "退出码: $?"
实测回显:
no main manifest attribute, in commons-dbcp2-2.14.0.jar
退出码: 1
no main manifest attribute 说明 jar 清单未声明 Main-Class,这是 DBCP 与自带主类的库(如 Commons Compress 的 Lister)最根本的区别。
4.2 读取 jar 清单
解出主 jar 的清单确认版本与编译目标:
cd /tmp && rm -rf mf && mkdir mf && cd mf
jar xf /opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar META-INF/MANIFEST.MF
grep -E "Implementation-Title|Implementation-Version|Bundle-Version|X-Compile-Target-JDK|Require-Capability" META-INF/MANIFEST.MF
实测回显:
Implementation-Title: Apache Commons DBCP
Implementation-Version: 2.14.0
X-Compile-Target-JDK: 1.8
Bundle-Version: 2.14.0
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
清单确认了两件事:版本是 2.14.0;字节码目标是 Java 8,因此 JDK 8 及以上都能运行。
4.3 主要公开类清单
列出与命令行诊断最相关的类,判断「有没有现成工具可借」:
jar tf /opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar | grep -E "BasicDataSource|PoolingDataSource|PoolableConnectionFactory|MXBean"
实测回显:
org/apache/commons/dbcp2/AbandonedTrace.class
org/apache/commons/dbcp2/BasicDataSource.class
org/apache/commons/dbcp2/BasicDataSourceFactory.class
org/apache/commons/dbcp2/BasicDataSourceMXBean.class
org/apache/commons/dbcp2/PoolableConnection.class
org/apache/commons/dbcp2/PoolableConnectionFactory.class
org/apache/commons/dbcp2/PoolableConnectionMXBean.class
org/apache/commons/dbcp2/PoolingDataSource$PoolGuardConnectionWrapper.class
org/apache/commons/dbcp2/PoolingDataSource.class
BasicDataSourceMXBean 的存在说明 DBCP 的可观测能力是通过 JMX 暴露的,而不是通过命令行——后文第八章会用到它对应的 getter 做状态采集。
五、自写诊断工具:池状态打印
本章给一个可直接当「命令行工具」用的诊断程序 PoolMonitor,它能打印池的实时状态快照,等价于其他连接池的 show status 命令。
package net.quzuo.demo;
import org.apache.commons.dbcp2.BasicDataSource;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
public class PoolMonitor {
public static void main(String[] args) throws Exception {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("org.h2.Driver");
ds.setUrl("jdbc:h2:mem:monitor;DB_CLOSE_DELAY=-1");
ds.setUsername("sa");
ds.setPassword("");
ds.setMaxTotal(5);
ds.setMaxIdle(5);
ds.setMinIdle(2);
ds.setInitialSize(2);
System.out.println("== 首次借还触发池初始化(initialSize=2 预建连接) ==");
ds.getConnection().close();
snapshot(ds);
List<Connection> borrowed = new ArrayList<>();
for (int i = 0; i < 4; i++) {
borrowed.add(ds.getConnection());
}
System.out.println("== 借出 4 条后 ==");
snapshot(ds);
for (Connection c : borrowed) {
c.close();
}
System.out.println("== 全部归还后 ==");
snapshot(ds);
ds.close();
}
private static void snapshot(BasicDataSource ds) {
System.out.println(String.format(
"maxTotal=%d maxIdle=%d minIdle=%d | numActive=%d numIdle=%d",
ds.getMaxTotal(), ds.getMaxIdle(), ds.getMinIdle(),
ds.getNumActive(), ds.getNumIdle()));
}
}
把该文件放到 Maven 工程的 src/main/java/net/quzuo/demo/PoolMonitor.java,编译后运行:
mvn -q compile exec:java -Dexec.mainClass=net.quzuo.demo.PoolMonitor
实测回显:
== 首次借还触发池初始化(initialSize=2 预建连接) ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=2
== 借出 4 条后 ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=4 numIdle=0
== 全部归还后 ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=4
5.1 无 Maven 时用 java -cp 直跑
目标机器没有 Maven 时,编译出 class 后用 java -cp 直接跑(类路径 = 编译产物目录 + 主 jar + 依赖目录):
cd /opt/dbcp-demo
javac -encoding UTF-8 -cp "/opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar:/opt/commons/commons-dbcp2-2.14.0/lib/*" -d target/classes src/main/java/net/quzuo/demo/PoolMonitor.java
java -Dfile.encoding=UTF-8 -cp "target/classes:/opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar:/opt/commons/commons-dbcp2-2.14.0/lib/*" net.quzuo.demo.PoolMonitor
实测回显(与 Maven 方式完全一致):
== 首次借还触发池初始化(initialSize=2 预建连接) ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=2
== 借出 4 条后 ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=4 numIdle=0
== 全部归还后 ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=4
诊断程序很轻,给 256MB 堆绰绰有余,显式限堆防止在受限机器上申请过大内存:
java -Xmx256m -Dfile.encoding=UTF-8 -cp "target/classes:/opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar:/opt/commons/commons-dbcp2-2.14.0/lib/*" net.quzuo.demo.PoolMonitor | head -1
实测回显:
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=2
六、jshell 交互实操
jshell 适合把库当「命令行」来探索:临时 new 一个池、敲几条语句看参数与状态,用完即走。把实验语句存成脚本(jshell 脚本模式不回显表达式值,必须显式 System.out.println):
cat > /opt/commons/dbcp-monitor.jsh <<'EOF'
import org.apache.commons.dbcp2.BasicDataSource;
import java.sql.*;
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("org.h2.Driver");
ds.setUrl("jdbc:h2:mem:jshell;DB_CLOSE_DELAY=-1");
ds.setUsername("sa");
ds.setPassword("");
ds.setMaxTotal(3);
ds.setMaxIdle(3);
System.out.println("参数: maxTotal=" + ds.getMaxTotal() + " maxIdle=" + ds.getMaxIdle());
Connection c = ds.getConnection();
Statement st = c.createStatement();
st.execute("CREATE TABLE probe (id INT PRIMARY KEY, v VARCHAR(16))");
st.execute("INSERT INTO probe VALUES (1,'h2')");
ResultSet rs = st.executeQuery("SELECT v FROM probe WHERE id=1");
rs.next();
System.out.println("查询结果: " + rs.getString(1));
System.out.println("借出状态 -> 活跃=" + ds.getNumActive() + " 空闲=" + ds.getNumIdle());
rs.close();
st.close();
c.close();
System.out.println("归还状态 -> 活跃=" + ds.getNumActive() + " 空闲=" + ds.getNumIdle());
ds.close();
/exit
EOF
带类路径启动 jshell 执行脚本:
cd /opt/commons
jshell --class-path "commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar:commons-dbcp2-2.14.0/lib/*" dbcp-monitor.jsh
实测回显:
Oct 13, 2026 4:40:36 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
参数: maxTotal=3 maxIdle=3
查询结果: h2
借出状态 -> 活跃=1 空闲=0
归还状态 -> 活跃=0 空闲=1
说明:首行 INFO: Created user preferences directory 是 jshell 首次运行创建偏好目录的提示,与 DBCP 无关,之后不再出现。三个要点:导入子包要用全限定名(import org.apache.commons.dbcp2.* 即可覆盖本例类);脚本文件模式不回显表达式值,必须 System.out.println;/exit 结束会话。想直接查版本,可在 jshell 中敲 BasicDataSource.class.getPackage().getImplementationVersion(),实测返回 2.14.0。
七、Maven 常用命令
有构建工具时,几条命令足以覆盖「看依赖、跑示例、查问题」:
| 命令 | 用途 |
|---|---|
| mvn dependency:tree | 核对 DBCP 及其传递依赖的真实版本 |
| mvn -q compile exec:java -Dexec.mainClass=你要跑的类 | 编译并运行示例类 |
| mvn -X compile | 调试构建,打印详细日志 |
| mvn -q clean | 清理编译产物 |
核对依赖树(确认 pool2 版本,排查版本冲突):
mvn -B dependency:tree
实测回显(输出节选,实测首尾):
[INFO] +- org.apache.commons:commons-dbcp2:jar:2.14.0:compile
[INFO] | +- org.apache.commons:commons-pool2:jar:2.13.0:compile
[INFO] | +- commons-logging:commons-logging:jar:1.3.5:compile
[INFO] | \- jakarta.transaction:jakarta.transaction-api:jar:1.3.3:compile
[INFO] \- com.h2database:h2:jar:2.5.252:compile
八、常见运维命令:连接数监控与状态导出
本章把第五章的诊断程序改成「可定期采集、可落盘」的运维形态。最简做法是定时把状态快照重定向到文件,再用 cat/tail 查看:
java -Dfile.encoding=UTF-8 -cp "target/classes:/opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar:/opt/commons/commons-dbcp2-2.14.0/lib/*" net.quzuo.demo.PoolMonitor > /var/log/dbcp-pool-status.txt
cat /var/log/dbcp-pool-status.txt
实测回显:
== 首次借还触发池初始化(initialSize=2 预建连接) ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=2
== 借出 4 条后 ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=4 numIdle=0
== 全部归还后 ==
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=4
只想要一行结果时用 tail 截取:
tail -1 /var/log/dbcp-pool-status.txt
实测回显:
maxTotal=5 maxIdle=5 minIdle=2 | numActive=0 numIdle=4
若要持续监控,把诊断逻辑包成循环即可(每次打印一行快照);也可以把 BasicDataSource 注册为 JMX MBean(它实现了 BasicDataSourceMXBean),再用 jconsole 连接查看 NumActive、NumIdle、MaxTotal 等属性——这是 DBCP 唯一的「面板式」观测途径。两条运维要点:numActive 长期贴近 maxTotal 说明容量不足或存在连接泄漏;numIdle 长期为 0 且 numActive 不高,则要怀疑连接没归还。
九、常见问题
Q1:DBCP 有没有像 redis-cli 那样的命令行?
没有。实测 java -jar commons-dbcp2-2.14.0.jar 报 no main manifest attribute(第四章),jar 内也没有任何 Main-Class 工具类。要在命令行看池状态,只能自写诊断程序(第五章)。
Q2:java -cp 跑诊断程序时类路径怎么写?
Linux 用冒号分隔,顺序建议「编译产物目录 : 主 jar : 依赖目录」,例如 target/classes:/opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar:/opt/commons/commons-dbcp2-2.14.0/lib/*。lib/* 交给 JVM 展开,不要用 shell 通配符。主类用全限定名 net.quzuo.demo.PoolMonitor。
Q3:jshell 脚本跑完没输出?
两个实测原因:脚本文件模式不回显表达式值,必须 System.out.println;导入子包要写全限定名。首行 Created user preferences directory 是首次运行提示,可忽略。
Q4:终端里程序输出的中文变问号?
locale 问题。export LANG=C.UTF-8,或给 java/jshell 加 -Dfile.encoding=UTF-8。若终端本身是 GBK 编码的远程工具,反过来设 -Dfile.encoding=GBK 或把终端改为 UTF-8。
Q5:怎么确认命令行走的是哪个 DBCP 版本?
两条路子:jar xf /opt/commons/commons-dbcp2-2.14.0/commons-dbcp2-2.14.0.jar META-INF/MANIFEST.MF 后看 Implementation-Version(第四章实测为 2.14.0);或在 Maven 工程里 mvn dependency:tree(第七章实测)。多版本共存时务必核对,避免 current 链接指向了旧版。
十、参考链接
- Apache Commons DBCP 官方主页:https://commons.apache.org/proper/commons-dbcp/
- 2.14.0 javadoc(
BasicDataSourceMXBean等 API):https://commons.apache.org/proper/commons-dbcp/apidocs/ - 2.14.0 发行包下载:https://downloads.apache.org/commons/dbcp/binaries/commons-dbcp2-2.14.0-bin.tar.gz
- Maven 中央仓库 2.14.0:https://repo1.maven.org/maven2/org/apache/commons/commons-dbcp2/2.14.0/
- commons-pool2(池实现来源库)文档:https://commons.apache.org/proper/commons-pool/
- jshell 用户指南:https://docs.oracle.com/en/java/javase/17/jshell/
- H2 Database 官网(示例所用内嵌数据库):https://h2database.com/