Springboot多数据源
SpringbootDurid多数据源
1. 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.17</version>
</dependency>
2. application配置
spring:
datasource:
primary:
url: jdbc:mysql://127.0.0.1:3306/test001?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
secondary:
url: jdbc:mysql://127.0.0.1:3306/test002?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
max-wait: 10000 #获取连接时最大等待时间,单位毫秒
initial-size: 10 #初始化时建立物理连接的个数
max-active: 100 #最大连接池数量
min-idle: 10 #最小连接数
time-between-eviction-runs-millis: 3600000 #检测连接的间隔时间
min-evictable-idle-time-millis: 300000 #连接的最小生存时间
test-while-idle: true #检测连接是否有效
test-on-borrow: false #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
validation-query: SELECT 1 #用来检测连接是否有效的sql
filters: stat #监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
stat-view-servlet:
url-pattern: /druid/*
reset-enable: true #允许清空统计数据
login-username: root #监控后台管理账号和密码
login-password: root
web-stat-filter:
url-pattern: /*
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
jpa:
database: mysql
generate-ddl: true
hibernate:
ddl-auto: create
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
3. 动态数据源
/**
* 动态数据源
* @author devcxl
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getContext();
}
}
3. 数据源配置
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource primaryDataSource, DataSource secondaryDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>(2);
targetDataSources.put(DataSourceType.PRIMARY, primaryDataSource);
targetDataSources.put(DataSourceType.SECONDARY, secondaryDataSource);
return new DynamicDataSource(primaryDataSource, targetDataSources);
}
/**
* 配置事务管理器,以便Spring事务管理可以处理多数据源
*/
@Bean
public PlatformTransactionManager transactionManager(DynamicDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
4. SpringAOP切面配置
切换数据库上下文
/**
* @author devcxl
*/
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<DataSourceType> CONTEXT_HOLDER = new ThreadLocal<>();
public static void setContext(DataSourceType dataSourceType) {
CONTEXT_HOLDER.set(dataSourceType);
}
public static DataSourceType getContext() {
return CONTEXT_HOLDER.get();
}
public static void clearContext() {
CONTEXT_HOLDER.remove();
}
}
AOP配置
/**
* 用于处理数据源注解切换逻辑
* @author devcxl
*/
@Aspect
@Component
public class DataSourceAspect {
@Around("@annotation(ds)")
public Object around(ProceedingJoinPoint point, DataSource ds) throws Throwable {
try {
DynamicDataSourceContextHolder.setContext(ds.value());
return point.proceed();
} finally {
DynamicDataSourceContextHolder.clearContext();
}
}
}