美文网首页springbootJAVA
spring boot动态数据源切换

spring boot动态数据源切换

作者: 异类_8b7a | 来源:发表于2019-09-29 13:30 被阅读0次

以后方便查看,故做一下笔记。也是参考网上朋友的内容,但时间比较久远不知道是那一篇,请谅解。
主要用得的是spring提供的AbstractRoutingDataSource类来实现数据源动态切换。
同时使用aop技术来实现在需要的地方声明使用哪种数据源即可。

  1. 继承AbstractRoutingDataSource
@Slf4j
public class DynamicDatasource extends AbstractRoutingDataSource {
    private static class DynamicDataSourceHolder {
        private static final DynamicDatasource instance = new DynamicDatasource();
    }

    public static final DynamicDatasource getInstance() {
        return DynamicDataSourceHolder.instance;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        DATASOURCE_MAP.putAll(targetDataSources);
        super.afterPropertiesSet();// 必须添加该句,否则新添加数据源无法识别到
    }
}
  1. 使用ThreadLocal保存当前线程的datasource情况:
public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    public static synchronized void setDataSourceKey(String key) {
        contextHolder.set(key);
    }

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

    public static void clearDataSourceKey() {
        contextHolder.remove();
    }
}
  1. 为mybatis注入多数据源配置
@Configuration
@MapperScan(basePackages = {"com.mappers"},  sqlSessionFactoryRef = "sqlSessionFactory")
public class JdbcConfig {
    @Value("${mybatis-plus.type-aliases-package}")
    private String typeAliasesPackage;
    @Value("${mybatis-plus.mapper-locations}")
    private String mapperLocation;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    @Bean
    @ConfigurationProperties(prefix = "hive.datasource")
    public DataSource hiveDataSource() {
        return new DruidDataSource();
    }

    @Bean(name = "impalaDataSource")
    @ConfigurationProperties(prefix = "impala.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    @Bean
    public DynamicDatasource dynamicDatasource() {
        DynamicDatasource dynamicDatasource = DynamicDatasource.getInstance();

        Map<Object, Object> datasourceMap = new HashMap<>();
        datasourceMap.put("datasource", dataSource());
        datasourceMap.put("impala", impalaDataSource());
        datasourceMap.put("hive", hiveDataSource());

        dynamicDatasource.setTargetDataSources(datasourceMap);

        dynamicDatasource.setDefaultTargetDataSource(dataSource());
        return dynamicDatasource;
    }


    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource());
        sqlSessionFactory.setMapperLocations(pathResolver.getResources(mapperLocation));

        sqlSessionFactory.setTypeAliasesPackage(typeAliasesPackage);
        return sqlSessionFactory.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}
  1. aop方式实现动态切换
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Ds {
    String value() default "datasource";
}
@Component
@Aspect
@Slf4j
public class DynamicDataSourceAspect {

    @Before("@annotation(com.annotation.Ds)")
    public void before(JoinPoint joinPoint) {
        Ds dsAnnotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(Ds.class);
        log.info("Switch datasource to [{}] in method [{}]", dsAnnotation.value(), joinPoint.getSignature());
        DynamicDataSourceContextHolder.setDataSourceKey(dsAnnotation.value());
    }

    @After("@annotation(com.annotation.Ds)")
    public void after(JoinPoint joinPoint) {
        log.info("Reset datasource to [{}] in method [{}]", DynamicDataSourceContextHolder.getDataSourceKey(), joinPoint.getSignature());
        DynamicDataSourceContextHolder.clearDataSourceKey();
    }
}

5.使用
只需要在需要使用指定事务的方法上使用@Ds进行申明即可。名称为指定数据源Map中的key。

相关文章

网友评论

    本文标题:spring boot动态数据源切换

    本文链接:https://www.haomeiwen.com/subject/kelfpctx.html