首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Tomcat Context 級資料源配置:實現 WebApp 級資料庫隔離

     編輯:MySQL 綜合教學

承接上文,本文聚焦 **Context 級資料源** 配置細節,展示如何為單一 WebApp 獨立定義 DataSource,實現多應用部署時的資料庫隔離、配置解耦與安全管控。

為何選擇 Context 級配置?

  • 隔離性:應用 A、B 使用不同資料庫/帳號,互不干擾。
  • 隨應用部署:`META-INF/context.xml` 打包進 WAR,部署即生效,無需操作 Tomcat 全域設定。
  • 環境差異化:開發/測試/生產環境各自維護 context.xml,CI/CD 替換部署。
  • 權限最小化:各應用僅擁有自身業務所需的 DB 權限。

標準配置範本 (src/main/webapp/META-INF/context.xml)

<Context antiResourceLocking="true">
  <!-- 核心 DataSource 定義 -->
  <Resource
      name="jdbc/myapp"
      auth="Container"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.cj.jdbc.Driver"
      url="jdbc:mysql://${DB_HOST}:3306/${DB_NAME}?useSSL=false&serverTimezone=Asia/Taipei&allowPublicKeyRetrieval=true"
      username="${DB_USER}"
      password="${DB_PASS}"
      maxTotal="30"
      maxIdle="15"
      minIdle="3"
      maxWaitMillis="5000"
      validationQuery="SELECT 1"
      testOnBorrow="true"
      testWhileIdle="true"
      timeBetweenEvictionRunsMillis="30000"
      minEvictableIdleTimeMillis="60000"
  />

  <!-- 可選:第二個資料源(如唯讀從庫) -->
  <Resource
      name="jdbc/myapp-ro"
      auth="Container"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.cj.jdbc.Driver"
      url="jdbc:mysql://${DB_RO_HOST}:3306/${DB_NAME}?useSSL=false&serverTimezone=Asia/Taipei"
      username="${DB_RO_USER}"
      password="${DB_RO_PASS}"
      maxTotal="20"
      maxIdle="10"
      minIdle="2"
      maxWaitMillis="3000"
      validationQuery="SELECT 1"
      testOnBorrow="true"
  />
</Context>

關鍵屬性解析

屬性說明建議值
antiResourceLocking防止 JAR 鎖定導致熱部署失敗(Windows 必開,Linux 可選)true
nameJNDI 名稱,代碼中用 `java:comp/env/` + name 查找jdbc/<app-name>
driverClassNameMySQL 8.0+ 用 `com.mysql.cj.jdbc.Driver`,5.1 用 `com.mysql.jdbc.Driver`對應驅動版本
urlJDBC URL,建議用環境變數佔位符,啟動腳本替換含時區、SSL、公開金鑰參數
maxTotal最大連線數,核心參數壓測決定,通常 20-100
validationQuery驗證查詢,MySQL 用 `SELECT 1`SELECT 1
testOnBorrow借用前驗證,防斷線true

web.xml 宣告 resource-ref(Servlet 3.0+ 可選,但建議保留)

<resource-ref>
  <description>MySQL Primary DataSource</description>
  <res-ref-name>jdbc/myapp</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

<resource-ref>
  <description>MySQL ReadOnly DataSource</description>
  <res-ref-name>jdbc/myapp-ro</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

Spring / 代碼中查找使用

// 純 JNDI 查找
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/myapp");

try (Connection conn = ds.getConnection()) {
  // 使用連線
}

// Spring 注入
@Resource(name = "jdbc/myapp")
private DataSource dataSource;

// Spring Boot 2.x/3.x application.yml
spring:
  datasource:
    jndi-name: java:comp/env/jdbc/myapp

環境變數化部署實踐

為了不將密碼寫入原始碼倉庫,採用 **啟動腳本 + 環境變數 + 模板替換** 方案:

#!/bin/bash
# bin/start-tomcat.sh
export DB_HOST="prod-db.internal"
export DB_NAME="myapp_prod"
export DB_USER="app_user"
export DB_PASS="$(vault kv get -field=password secret/myapp/db)"

# 替換 context.xml 中的佔位符
envsubst < /opt/tomcat/webapps/myapp/META-INF/context.xml.template \
  > /opt/tomcat/webapps/myapp/META-INF/context.xml

exec /opt/tomcat/bin/catalina.sh run

`context.xml.template` 中使用 `${DB_HOST}` 等語法,`envsubst` (GNU gettext) 會自動替換環境變數值。

多環境配置管理策略

環境配置來源部署方式
開發開發者本地 `.env` / Docker Compose `environment`IDE 熱部署 / `mvn tomcat7:run`
測試CI/CD 變數 / K8s ConfigMapHelm chart `values.yaml` 注入
預發/生產Vault / 參數存儲 / K8s SecretArgoCD / Helm + SealedSecrets

常見坑與避雷

  • context.xml 未生效:檢查 `antiResourceLocking="true"`、WAR 解壓後 `META-INF/context.xml` 存在、Tomcat `deployXML="true"` (預設)。
  • 資料源名稱衝突:嚴格命名 `jdbc/`、`jdbc/-ro`,避免同名覆蓋。
  • 驅動衝突:驅動 JAR **只能放在 `$CATALINA_HOME/lib`**,不能放在 `WEB-INF/lib`,否則會出現 `ClassCastException` 或 `Cannot create JDBC driver`。
  • 連線池未釋放:代碼務必 `try-with-resources` 或 `finally { close() }`,配合 `removeAbandonedOnBorrow` 雙重保險。

Context 級資料源是 Java Web 標準部署模式的基石。掌握其配置、注入、環境化流程,能讓應用在開發、測試、生產環境間無縫流轉,同時守住安全底線。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved