Spring 應用中數據源配置看似簡單,但生產環境往往面臨多環境切換、敏感信息外部化、多数據源路由等挑戰。本文從經典 XML 配置切入,遞進至現代 Spring Boot 自動配置,給出生產級數據源配置全景指南。
<!-- 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() 創建物理連接,**嚴禁生產使用**。
<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 為備選。
# 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),實現配置與基礎設施解耦。
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 方法自動路由到從庫,寫操作走主庫。
# 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)leakDetectionThreshold)@Transactional("masterTxManager") 顯式指定)hikaricp_* 指標)數據源配置是應用與數據庫的「生命線」。從 XML 佔位符到 Spring Boot YAML,從單一連接池到動態路由,核心原則始終是:外部化配置、連接池生產化、敏感信息加密、路由邏輯顯式化、監控可觀測。掌握這套演進路徑,能讓你在單體遷移微服務、上雲容器化、多雲部署等架構變革中,始終守住數據訪問層的穩健與安全。