Tomcat 內建的資料源(DataSource)透過 JNDI 註冊,實現資料庫連接池的容器化管理。本文系統講解 JDBC 2.0 DataSource 規範、連接池原理、JNDI 綁定機制、server.xml/web.xml 雙重配置與程式碼獲取全流程。
| 傳統方式痛點 | DataSource 解決方案 |
|---|---|
| 每請求建立/關閉連接,效能極差 | 連接池預建連接,按需借用/歸還 |
| 驅動載入、認證重複開銷大 | 連接復用,避免重複握手 |
| 連接洩漏難追蹤 | 池管理生命週期,支援檢測/回收 |
| 程式碼硬編碼連接參數 | 配置外部化,環境隔離 |
jdbc/BookDB)bind(name, obj) 綁定、lookup(name) 查找org.apache.commons.dbcp.BasicDataSourceFactory(DBCP 1.x)或 org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory(DBCP 2.x / Tomcat 8+)<Context path="/bookstore" docBase="bookstore" reloadable="true">
<Resource name="jdbc/BookDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="dbuser" password="123456"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/BookDB?autoReconnect=true"
factory="org.apache.commons.dbcp.BasicDataSourceFactory" />
</Context>
關鍵屬性:
auth="Container":容器管理生命週期(推薦)maxActive:最大活躍連接數(0=無限制)maxIdle:最大空閒連接數maxWait:獲取連接最長等待毫秒數(-1=無限等待)validationQuery:連接有效性檢測 SQL(如 SELECT 1)testOnBorrow:借用時檢測(效能與安全的權衡)<resource-ref> <description>DB Connection</description> <res-ref-name>jdbc/BookDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
作用:宣告 Web 應用依賴此 JNDI 資源,res-ref-name 需與 server.xml 中 name 一致(不含 jdbc/ 前綴時自動補全)。
// 標準 JNDI 查找
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/BookDB");
// 獲取連接(從池借用)
Connection conn = ds.getConnection();
try {
// 業務操作
} finally {
// 關鍵:歸還連接池,而非真正關閉物理連接
conn.close();
}
| 場景 | 建議配置 |
|---|---|
| 生產環境連接洩漏防護 | removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" |
| 連接有效性保障 | validationQuery="SELECT 1" testOnBorrow="true" testWhileIdle="true" timeBetweenEvictionRunsMillis="30000" |
| MySQL 斷線重連 | URL 含 autoReconnect=true + 驅動 5.1.39+ / 8.0+ + testOnBorrow=true |
| Druid/HikariCP 替換 DBCP | 修改 factory 類,屬性名對應調整(如 maxActive→maxPoolSize) |
NameNotFoundException:檢查 java:comp/env/ 前綴、res-ref-name 拼寫、Context 路徑maxWait、檢查連接洩漏、擴大池大小validationQuery、檢查防火牆/資料庫 wait_timeouttomcat-dbcp 或排除應用依賴Spring Boot 等框架透過 @ConfigurationProperties 直接配置 DataSource Bean,無需 JNDI 配置,更適合微服務/容器化部署。但理解 Tomcat JNDI DataSource 機制,對排查遷移老專案、理解容器管理資源本質仍有重要價值。