隨著用戶增長,單一資料庫成為系統瓶頸。將業務拆分到不同資料庫(如 MySQL 處理用戶、Oracle 處理訂單),再透過 JNDI 統一管理資料源,是邁向分布式架構的關鍵一步。本文示範在 Tomcat 中配置多資料源,並在 Web 應用中透過 JNDI 查找使用。
採用 JNDI(Java Naming and Directory Interface)將資料源註冊到 Tomcat 全局命名空間,應用透過 java:comp/env 查找,實現資料源與代碼解耦。
server.xml(全局資料源)<Context>
<!-- MySQL 資料源 -->
<Resource name="jdbc/mysql"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/test"
username="admin"
password="admin"
maxActive="100"
maxIdle="30"
maxWait="10000" />
<!-- Oracle 資料源 -->
<Resource name="jdbc/orcl"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.2:1521:orcl"
username="trigger"
password="trigger"
maxActive="50"
maxIdle="10"
maxWait="10000" />
</Context>
關鍵屬性說明:
name:JNDI 名稱,需與 web.xml 映射一致maxActive/maxIdle/maxWait:連接池核心參數$CATALINA_HOME/libweb.xml(資源引用映射)<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/mysql</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/orcl</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
注意:<res-ref-name> 必須與 server.xml 中 Resource name 完全一致,否則會報 NameNotFoundException。
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/mysql"); // 或 jdbc/orcl
Connection conn = ds.getConnection();
// 使用連接...
conn.close(); // 歸還連接池
配置 Tomcat server.xml
↓
配置項目 web.xml resource-ref
↓
引入資料庫驅動包到 Tomcat lib
↓
代碼中 JNDI 查找 DataSource → getConnection()
| 問題 | 原因 | 解決 |
|---|---|---|
| NameNotFoundException | JNDI 名稱不匹配 | 核對 server.xml name 與 web.xml res-ref-name |
| ClassNotFoundException (Driver) | 驅動包未放入 Tomcat lib | 將 mysql-connector-java.jar、ojdbc.jar 放入 $CATALINA_HOME/lib |
| 連接洩漏 | 未 close 連接 | 使用 try-with-resources 或 finally 確保關閉 |
| 事務跨資料庫 | 單一 DataSource 不支援分佈式事務 | 引入 JTA (Atomikos/Bitronix) 或採用最終一致性模式 |
JNDI 將資料源配置從代碼中剝離,實現「開發不關心部署細節,運維不關心業務邏輯」的關注點分離。這是邁向微服務、雲原生架構的基礎技能。下一步可探索 Spring 的 @Primary、@Qualifier 多資料源自動裝配,或 ShardingSphere 等中間件實現透明分庫分表。