首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring JDBC 數據源配置最佳實踐:屬性佔位符與多数據源擴展

     編輯:Java 相關知識

Spring 應用中數據源配置看似簡單,但生產環境往往面臨多環境切換、敏感信息外部化、多数據源路由等挑戰。本文從經典 XML 配置切入,遞進至現代 Spring Boot 自動配置,給出生產級數據源配置全景指南。

經典 XML 配置:屬性佔位符外部化


<!-- XXX-data.xml -->
<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<!-- applicationContext.xml -->
<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list><value>classpath:jdbc.properties</value></list>
    </property>
</bean>

# jdbc.properties
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.0.18:1521:dbname
jdbc.username=app_user
jdbc.password=encripted_password

優點:配置與代碼分離、多環境維護獨立 properties 文件、敏感信息可加密存儲。缺點:DriverManagerDataSource **非連接池**,每次 getConnection() 創建物理連接,**嚴禁生產使用**。

生產級連接池選型:HikariCP 為首選


<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <!-- 核心池參數 -->
    <property name="maximumPoolSize" value="${jdbc.pool.maxSize:20}"/>
    <property name="minimumIdle" value="${jdbc.pool.minIdle:5}"/>
    <property name="idleTimeout" value="${jdbc.pool.idleTimeout:300000}"/>
    <property name="connectionTimeout" value="${jdbc.pool.connectionTimeout:30000}"/>
    <property name="maxLifetime" value="${jdbc.pool.maxLifetime:1800000}"/>
    <property name="poolName" value="PrimaryHikariPool"/>
</bean>

HikariCP 以極致性能、零依賴、可靠性著稱,Spring Boot 2.x 默認連接池。Druid、Tomcat JDBC Pool、DBCP2 為備選。

Spring Boot 自動配置:零 XML、約定優於配置


# application.yml
spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: org.postgresql.Driver
    url: jdbc:postgresql://${DB_HOST:localhost}:5432/${DB_NAME:myapp}
    username: ${DB_USER:app}
    password: ${DB_PASSWORD:secret}
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 300000
      max-lifetime: 1800000
      pool-name: PrimaryPool

環境變量 ${VAR:default} 支持容器化部署(K8s ConfigMap/Secret、Docker Compose .env),實現配置與基礎設施解耦。

多数據源路由:AbstractRoutingDataSource 實現讀寫分離


public class RoutingDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSourceKey(String key) { contextHolder.set(key); }
    public static void clear() { contextHolder.remove(); }

    @Override
    protected Object determineCurrentLookupKey() { return contextHolder.get(); }
}

@Configuration
public class DataSourceConfig {
    @Primary @Bean("masterDataSource") DataSource master() { ... }
    @Bean("slaveDataSource") DataSource slave() { ... }

    @Bean DataSource routingDataSource() {
        RoutingDataSource rds = new RoutingDataSource();
        Map<Object, Object> target = new HashMap<>();
        target.put("master", master());
        target.put("slave", slave());
        rds.setTargetDataSources(target);
        rds.setDefaultTargetDataSource(master());
        return rds;
    }
}

配合 AOP 切面:


@Aspect @Component
public class DataSourceRoutingAspect {
    @Before("@annotation(ReadOnly)")
    public void setSlave() { RoutingDataSource.setDataSourceKey("slave"); }

    @Before("@annotation(WriteOperation)")
    public void setMaster() { RoutingDataSource.setDataSourceKey("master"); }

    @After("@annotation(ReadOnly) || @annotation(WriteOperation)")
    public void clear() { RoutingDataSource.clear(); }
}

使用:@ReadOnly 方法自動路由到從庫,寫操作走主庫。

敏感信息加密:Jasypt 整合


# pom.xml
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

# application.yml
jasypt:
  encryptor:
    password: ${JASYPT_PASSWORD:strong_master_key}
    algorithm: PBEWithMD5AndDES

spring:
  datasource:
    password: ENC(Gx8vK9...encrypted_value...)

啟動時需提供 JASYPT_PASSWORD 環境變量,配置文件中不再出現明文密碼。

避坑檢查清單

  • ❌ 生產環境使用 DriverManagerDataSource / BasicDataSource (DBCP1)
  • ❌ 連接池參數使用默認值未經壓測調優
  • ❌ 密碼明文寫入配置文件、提交代碼倉庫
  • ❌ 缺乏連接洩漏檢測(HikariCP leakDetectionThreshold)
  • ❌ 多数據源事務管理混亂(需 @Transactional("masterTxManager") 顯式指定)
  • ✅ 連接池監控指標接入 Prometheus/Grafana(hikaricp_* 指標)
  • ✅ 定期演練連接池耗盡、數據庫故障切換預案

結語

數據源配置是應用與數據庫的「生命線」。從 XML 佔位符到 Spring Boot YAML,從單一連接池到動態路由,核心原則始終是:外部化配置、連接池生產化、敏感信息加密、路由邏輯顯式化、監控可觀測。掌握這套演進路徑,能讓你在單體遷移微服務、上雲容器化、多雲部署等架構變革中,始終守住數據訪問層的穩健與安全。

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