1. 程式人生 > >基於Spring Boot 動態主從資料庫路由

基於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 
版權宣告:本文為博主原創文章,轉載請附上博文連結!