Springboot 整合Mybatis多数据源并动态切换

首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,两张库都有一张同样的表(偷懒),表名 t_user

字段名 类型 备注
id int 主键自增ID
name varchar 名称



表中分别添加两条不同数据,方便测试 主数据库记录name为xiaobin,从库为xiaoliu。
目录结构



开始使用Springboot 整合mybatis,首先引入pom文件。
   

   4.0.0
   
       org.springframework.boot
       spring-boot-starter-parent
       2.1.4.RELEASE
   
   com.xiaobin
   mysql_master_slave
   1.0-SNAPSHOT

   
       1.8
       1.18.6
       1.3.2
       1.18.6
   

   
       
       
           org.springframework.boot
           spring-boot-starter-web
       
       
       
           org.projectlombok
           lombok
           ${lombok.version}
       
       
       
           org.springframework.boot
           spring-boot-starter-test
       
       
       
           org.projectlombok
           lombok
           ${lombox.version}
       
       
       
           org.mybatis.spring.boot
           mybatis-spring-boot-starter
           ${mybatis.version}
       
       
       
           mysql
           mysql-connector-java
       
       
           org.springframework.boot
           spring-boot-starter-jdbc
       
       
       
           com.alibaba
           druid-spring-boot-starter
           1.1.10
       
       
       
           org.springframework.boot
           spring-boot-starter-aop
       

   

动态数据源配置

这里使用的数据源为druid,实现数据源之间的切换用@DataSource自定义注解,配置Aop进行切换 application.yml 配置文件。

spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          xiaobin-master: # 主数据源
            driverClassName: com.mysql.jdbc.Driver
            username: root
            password: root
            url: jdbc:mysql://localhost:3306/master_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
          xiaobin-slave: # 从数据源
            driverClassName: com.mysql.jdbc.Driver
            username: root
            password: root
            url: jdbc:mysql://localhost:3306/slave_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
mybatis:
 mapper-locations: classpath:mapper/*.xml

多数据源配置类

@Configuration
@Component
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.druid.xiaobin-master")
    public DataSource  xiaobinMasterDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.xiaobin-slave")
    public DataSource  xiaobinSlaveDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource xiaobinMasterDataSource, DataSource xiaobinSlaveDataSource) {
        Map targetDataSources = new HashMap<>();
        targetDataSources.put("xiaobin-master",xiaobinMasterDataSource);
        targetDataSources.put("xiaobin-slave", xiaobinSlaveDataSource);
        return new DynamicDataSource(xiaobinMasterDataSource, targetDataSources);
    }
}

动态数据源切换类

public class DynamicDataSource  extends AbstractRoutingDataSource {

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

    public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

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

自定义@DataSource注解
在需要切换数据的Dao添加此注解

/**
 * 备注:自定义数据源选择注解
 **/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String name() default "";
}

Aop切面类配置

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.xiaobin.annotation.DataSource)")
    public void dataSourcePointCut() {

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        DataSource dataSource = method.getAnnotation(DataSource.class);
        if(dataSource == null){
            DynamicDataSource.setDataSource("xiaobin-master");
        }else {
            DynamicDataSource.setDataSource(dataSource.name());
        }

        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }
}

启动配置注解信息,重要(不然运行会报错)

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@MapperScan(basePackages = "com.xiaobin.mapper")
@Import({DynamicDataSourceConfig.class})
public class StartApp {
    public static void main(String[] args) {
        SpringApplication.run(StartApp.class);
    }
}
测试controller

@RestController
@RequestMapping
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @GetMapping("/{name}/list")
    public List list(@PathVariable("name")String name){
        if(name.equals("master")){
            return userMapper.queryAllWithMaster();
        }else{
            return userMapper.queryAllWithSlave();
        }
    }
}

效果图

更具路径传值,进行主从数据源切换



你可能感兴趣的:(Springboot 整合Mybatis多数据源并动态切换)