1.config配置类
/**
*
*注解类,后面用来标注DAO方法
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface DS {
String value();
}
/**
*
* 简单的路由规则,用来设置当前数据库连接
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
Object key;
if (DynamicDataSourceHolder.isMaster()) {
key = DynamicDataSourceHolder.MASTER;
} else if (DynamicDataSourceHolder.isForm()) {
key = DynamicDataSourceHolder.FORM;
} else {
key = DynamicDataSourceHolder.MASTER;
}
return key;
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
}
}
/**
* 配置类,用来读取yml文件中数据库配置
*
*/
@ConfigurationProperties(prefix = "dynamic")
public class DynamicDataSourceConfig {
private Map<String,DruidDataSource> datasources = new HashMap<>();
public Map<String,DruidDataSource> getDatasources() {
return datasources;
}
public void setDatasources(Map<String,DruidDataSource> datasources) {
this.datasources = datasources;
}
}
/**
* 动态数据源配置类,用来加载配置的数据源
*/
@Configuration
@EnableConfigurationProperties(DynamicDataSourceConfig.class)
public class DynamicDataSourceConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSourceConfiguration.class);
private final DynamicDataSourceConfig dynamicDataSourceConfig;
public DynamicDataSourceConfiguration(DynamicDataSourceConfig dynamicDataSourceConfig) {
this.dynamicDataSourceConfig = dynamicDataSourceConfig;
}
@Bean
public DynamicDataSource dynamicDataSource() throws SQLException {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> dataSources = new HashMap<>(2);
for (Map.Entry<String, DruidDataSource> entry : dynamicDataSourceConfig.getDatasources().entrySet()) {
String key = entry.getKey();
DruidDataSource dataSource = entry.getValue();
if (!key.equals(DynamicDataSourceHolder.MASTER)) {
dataSources.put(key, dataSource);
}
dataSource.init();
LOGGER.info("init dataSource:{}", key);
}
DruidDataSource masterDataSource = dynamicDataSourceConfig.getDatasources().get(DynamicDataSourceHolder.MASTER);
if (masterDataSource == null) {
throw new IllegalArgumentException("Undefined master database");
}
dataSources.put(DynamicDataSourceHolder.MASTER, masterDataSource);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
dynamicDataSource.setTargetDataSources(dataSources);
return dynamicDataSource;
}
}
/**
* 配合注解使用,用来标记DAO方法
*/
public class DynamicDataSourceHolder {
public static final String MASTER = "master";
public static final String SLAVE = "slave";
private static final ThreadLocal<String> HOLDER = new ThreadLocal<>();
private static void putDataSourceKey(String key) {
HOLDER.set(key);
}
public static String getDataSourceKey() {
return HOLDER.get();
}
public static void markMaster() {
putDataSourceKey(MASTER);
}
public static void markSLAVE() {
putDataSourceKey(SLAVE);
}
public static boolean isMaster() {
return MASTER.equals(HOLDER.get());
}
public static boolean isSlave() {
return SLAVE.equals(HOLDER.get());
}
}
/**
* 切面类,通过@DS注解动态给DAO方法注入指定的数据源
*/
@Order(-1)
@Aspect
@Component
public class DynamicDatasourceAop {
@Pointcut(value = "execution(* io.nonda.zus.common.repository.dao.mybatis.pgsql.*.*(..))")
public void dao() {
}
@Before("dao()")
public void beforeService(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
DS ds = method.getAnnotation(DS.class);
if (null == ds) {
DynamicDataSourceHolder.markMaster();
} else if (DynamicDataSourceHolder.FORM.equals(ds.value())) {
DynamicDataSourceHolder.markFORM();
} else {
DynamicDataSourceHolder.markMaster();
}
}
}
2.yml配置: 如果是mysql,只需要修改driver-class-name驱动类即可
dynamic:
datasources:
master:
url: jdbc:postgresql://nonxxxt-1.rds.xxx.com:5432/test
username: xx
password: xxx
driver-class-name: org.postgresql.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 1
min-idle: 5
max-active: 5
max-wait: 60000
time-between-eviction-runs-millisr: 28000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall,slf4j
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
use-global-data-source-stat: true
remove-abandoned: true
print-sql: false
slave:
url: jdbc:postgresql://xx-x-qa.xxx.us-east-1.rds.amazonaws.com:5432/test
username: xx
password: xxx
driver-class-name: org.postgresql.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 1
min-idle: 5
max-active: 5
max-wait: 60000
time-between-eviction-runs-millisr: 28000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall,slf4j
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
use-global-data-source-stat: true
remove-abandoned: true
print-sql: false
3.使用方式
public interface IObdCodeInfoDAO {
// aop动态解析的时候,设置了不指定默认为master数据源
int deleteByPrimaryKey(String id);
// 指定master数据源
@DS(DynamicDataSourceHolder.MASTER)
int insert(ObdCodeInfoPO record);
// 指定slave数据源
@DS(DynamicDataSourceHolder.SLAVE)
int insertSelective(ObdCodeInfoPO record);
}
通过上面的配置,即可简单的完成多数据源的配置和使用,如果需要增加数据源,在以上代码上扩展即可。
MARK:
最近在关注一个手机挖矿项目,叫Bee蜜蜂币。
APP 下载链接: https://bee.com/sc/
推荐码:lei911gang
手机免费挖矿,感兴趣的可以一起加入。