基于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 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/kingice1014/article/details/84285402