基於Spring Boot 動態主從資料庫路由
本文簡單的介紹一下基於Spring boot框架動態連線多資料來源的實現,在配置檔案中新增多個數據源,採用主從配置的方式,配置zjsz、cloud兩個資料庫。
專案的目錄結構:
application.properties
核心主要是dynamic和aop目錄
1.首先配置資料來源資訊,在spring5.x之後開始預設使用HikariCP來做資料來源
@Configuration
public class DataSourceConfig {
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spirng.master.datasource")
public HikariDataSource masterDataSource() {
return new HikariDataSource();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spirng.slave.datasource")
public HikariDataSource slaveDataSource() {
return new HikariDataSource();
}
//動態資料來源
@Bean(name = "dynamicDataSource")
//解決互相依賴關係
@DependsOn({ "masterDataSource", "slaveDataSource"})
@Primary
public DataSource getDataSource() {
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources());
return dataSource;
}
private Map<Object, Object> targetDataSources() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER.getType(), masterDataSource());
targetDataSources.put(DataSourceType.SLAVE.getType(), slaveDataSource());
return targetDataSources;
}
}
public enum DataSourceType {
SLAVE("slave", "從庫"),
MASTER("master", "主庫");
private String type;
private String name;
DataSourceType(String type, String name) {
this.type = type;
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.自定義Datasource註解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
public @interface DataSource {
/**
* 資料庫路由
*/
DataSourceType value() default DataSourceType.MASTER;
}
3.使用ThreadLocal來保證從@DataSource獲取的路由key是執行緒安全的
public class DynamicDataSourceHolder {
private static final ThreadLocal<String> holder = new ThreadLocal<>();
public static void putDataSource(DataSourceType dataSourceType) {
holder.set(dataSourceType.getType());
}
public static String getDataSouce() {
return holder.get();
}
}
4.繼承AbstractRoutingDataSource並重寫determineCurrentLookupKey法法
使用AbstractRoutingDataSource 的實現類,進行靈活的切換,可以通過AOP或者手動程式設計設定當前的DataSource,這樣的編寫方式比較好。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
if (DynamicDataSourceHolder.getDataSouce() != null) {
return DynamicDataSourceHolder.getDataSouce();
}
return DataSourceType.MASTER.getType();
}
}
5.使用AOP進行攔截帶有@DataSource註解的方法,並獲取註解的值,進行動態資料來源操作
@Aspect
@Component
public class DataSourceAspect implements Ordered {
// @Pointcut("execution(public * com.aop.jdbc.impl..*.*(..))")
// public void dynamic() {
//
// }
@Before(value = "@annotation(dataSource)")
public void dataSourcePoint(JoinPoint joinPoint, DataSource dataSource) {
DynamicDataSourceHolder.putDataSource(dataSource.value());
}
@Override
public int getOrder() {
return -1;
}
}
6.使用方法
@Service("testService")
public class TestServiceImpl implements ITestService {
@Autowired
private OwnCodeMapper ownCodeMapper;
@DataSource(DataSourceType.MASTER)
@Override
public String save() {
System.out.println("=======save======進入主庫操作========save======");
System.out.println("刪除影響行數:" + this.ownCodeMapper.deleteByPrimaryKey(2));
return null;
}
@DataSource(DataSourceType.SLAVE)
@Override
public String query() {
System.out.println("=======query======進入從庫操作=========query=====");
System.out.println("查詢結果:" + this.ownCodeMapper.selectByPrimaryKey(36));
return null;
}
}
到此就完成了動態主從路由的程式碼開發。
原始碼地址,大家幫忙star哦!!
---------------------
作者:攻城遭雷劈
來源:CSDN
原文:https://blog.csdn.net/m0_37444820/article/details/83039165
版權宣告:本文為博主原創文章,轉載請附上博文連結!