Java SpringBoot项目配置postgreSQL多数据源

1、依赖

这里只写多数据源的依赖,其他的postgresql、mybatis-plus等依赖,都在现在的项目中有

1
2
3
4
5
6
<dependency>    
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.xx</version>
<scope>compile</scope>
</dependency>

2、配置

ps:公司项目中,配置都写在主包的datasource中
配置多数据源
增加类,这里配置了两个数据源的样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Configuration
public class MultipleDataSourceConfig {

@Bean("master")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource createMasterDataSource(){
return new DruidDataSource();
}

@Bean("slave1")
@ConfigurationProperties(prefix = "spring.datasource.slave1")
public DataSource createSlave1DataSource(){
return new DruidDataSource();
}

/**
* 设置动态数据源,通过@Primary 来确定主DataSource
* @return
*/
@Bean
@Primary
public DataSource createDynamicDataSource(@Qualifier("master") DataSource master, @Qualifier("slave1") DataSource slave1){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
//设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(master);
//配置多数据源
Map<Object, Object> map = new HashMap<>();
map.put("master",master);
map.put("slave1",slave1);
dynamicDataSource.setTargetDataSources(map);
return dynamicDataSource;
}
}

重写determineCurrentLookupKey() 方法

1
2
3
4
5
6
7
8
9
10
public class DynamicDataSource extends AbstractRoutingDataSource {

Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);

@Override
protected Object determineCurrentLookupKey() {
logger.info("------------------当前数据源 {}", DynamicDataSourceSwitcher.getDataSource());
return DynamicDataSourceSwitcher.getDataSource();
}
}

AbstractRoutingDataSource 是spring jdbc提供的操作读数据源的抽象类,重写determineCurrentLookupKey() 指定获得当前数据源

实现操作数据源的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class DynamicDataSourceSwitcher {

static Logger logger = LoggerFactory.getLogger(DynamicDataSourceSwitcher.class);

public static final String Mater = "master";
public static final String Slave1 = "slave1";

private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

public static void setDataSource(String name){
logger.info("-------- 设置数据源数据源为 :{} ", name);
contextHolder.set(name);
}

public static String getDataSource(){
if (StringUtils.isEmpty(contextHolder.get())) {
setDataSource(Mater);
}
return contextHolder.get();
}

public static void cleanDataSource(){
contextHolder.remove();
}
}

实现注解使用数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.METHOD
})
public @interface MyDataSource {
String value() default "master";
}

@Aspect
@Component
@Order(1)
public class DynamicDataSourceAspect {
private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

/**
* 切入点只对@Service注解的类上的@DataSource方法生效
* @param myDataSource
*/
@Pointcut(value="@within(org.springframework.stereotype.Service) && @annotation(myDataSource)" )
public void dynamicDataSourcePointCut(MyDataSource myDataSource){}

@Before(value = "dynamicDataSourcePointCut(myDataSource)")
public void switchDataSource(MyDataSource myDataSource) {
DynamicDataSourceSwitcher.setDataSource(myDataSource.value());
}

/**
* 切点执行完后 切换成主数据库
* @param myDataSource
*/
@After(value="dynamicDataSourcePointCut(myDataSource)")
public void after(MyDataSource myDataSource){
DynamicDataSourceSwitcher.cleanDataSource();
}
}

3、配置postgresql数据库地址

通过端口号区分两个数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
spring:
profiles: multi
datasource:
master:
url: jdbc:postgresql://127.0.0.1:5634/postgres
username: postgre
password: 123456
driver-class-name: org.postgresql.Driver
type: com.alibaba.druid.pool.DruidDataSource
name: master
initialize: true
filters: stat
slave1:
url: jdbc:postgresql://127.0.0.1:6064/postgres
username: postgre
password: 123456
driver-class-name: org.postgresql.Driver
type: com.alibaba.druid.pool.DruidDataSource
name: slave1
initialize: true
filters: stat

4、使用多数据源

在实现类方法上加注解

@MyDataSource(value = DynamicDataSourceSwitcher.Slave1)