美文网首页Spring Boot&Spring CloudspringbootIT技术篇
在Spring Boot中配置多数据源&使用动态数据源

在Spring Boot中配置多数据源&使用动态数据源

作者: 简单的土豆 | 来源:发表于2017-03-20 16:19 被阅读1091次

    配置文件方式,这里使用YMAL,你也可以使用传统的Properties,只要将:更换为.的形式即可。

    spring:
      datasource:
        one:
          setype: com.alibaba.druid.pool.DruidDataSource
          url: 你的JDBC URL
          username: 你的用户名
          password: 你的密码
          driver-class-name: com.mysql.jdbc.Driver
        two:
          setype: com.alibaba.druid.pool.DruidDataSource
          url: 你的JDBC URL
          username: 你的用户名
          password: 你的密码
          driver-class-name: com.mysql.jdbc.Driver
    

    创建DynamicDataSource

    public class DynamicDataSource extends AbstractRoutingDataSource {  
      @Override    
      protected Object determineCurrentLookupKey() {       
         return DataSourceContextHolder.getType();    
        }
    }
    

    创建DataSourceContextHolder 类并使用ThreadLocal来存放数据源类型变量

    public class DataSourceContextHolder {
        private static final Logger LOGGER = LoggerFactory.getLogger(ProductContextHolder.class);
        public static final List<Object> supportList= new ArrayList<>();
        // 线程本地环境
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
        public static void setType(String type) {
            contextHolder.set(type);
            LOGGER.debug("==============切换数据源,类型:" + type + "================");
        }
        public static String getType() {
            return (contextHolder.get());
        }
        public static void clear() {
            contextHolder.remove();
        }
        public static boolean support(String type) {
            return supportList.contains(type);
        }
    }
    
    

    创建一个Configurer来配置数据源,这里仅配置两个作为参考,如果你看过 使用Spring配置动态数据源实现读写分离 的话,你会觉得这非常简单,只不过是XML配置方式 =》 编程配置方式的转化。
    有趣的是如果你要使用非默认数据源,如Druid,数据源配置项datasource.setype.com.alibaba.druid.pool.DruidDataSource并不能很好工作,只能使用DataSourceBuilder的时候显式指定,至少在Spring Boot 1.4是这样。

    @Configuration
    public class DataSourceConfigurer {
    
        @Bean
        @Primary
        @ConfigurationProperties(prefix="spring.datasource.one")
        public DataSource oneDataSource() {
            return DataSourceBuilder
                    .create()
                    .type(DruidDataSource.class)
                    .build();
        }
    
        @Bean
        @ConfigurationProperties(prefix="spring.datasource.two")
        public DataSource twoDataSource() {
            return DataSourceBuilder
                    .create()
                    .type(DruidDataSource.class)
                    .build();
        }
        @Bean
        public DynamicDataSource dataSource(){
            DynamicDataSource dynamicDataSource = new DynamicDataSource();
            Map<Object, Object> targetDataSources = Maps.newHashMap();
            targetDataSources.put("one", oneDataSource());
            targetDataSources.put("two", twoDataSource());
            dynamicDataSource.setTargetDataSources(targetDataSources);
    
            DataSourceContextHolder.supportList.addAll(targetDataSources.keySet());
    
            return dynamicDataSource;
        }
    }
    

    好了,动态数据源配置完成,至于在什么时候切换数据源根据你的实际情况而定,方式有很多,比如使用注解、做切面、用拦截器拦截参数等等,这里就不做赘述了。在使用void DataSourceContextHolder.setType(String type)切换数据源前最好能调用boolean DataSourceContextHolder.support(String type)判断是否支持该数据源。

    相关文章

      网友评论

      • 兔贩子:ProductContextHolder是不是写错了?
        我在Filter中调用DataSourceContextHolder.setType("two")没有成功切换数据源。
        楼主知道什么情况吗?
        简单的土豆:@兔贩子 看了下,没问题呀,可能是你说的原因吧 Mybatis是没问题的。
        兔贩子:@简单的土豆
        @Configuration
        public class DataSourceConfigurer {

        @Bean
        @primary
        @ConfigurationProperties(prefix = "spring.datasource")
        public DataSource oneDataSource() {
        return DataSourceBuilder
        .create()
        .type(DruidDataSource.class)
        .build();
        }

        @Bean
        @ConfigurationProperties(prefix = "spring.datasource2")
        public DataSource twoDataSource() {
        return DataSourceBuilder
        .create()
        .type(DruidDataSource.class)
        .build();
        }

        @Bean
        public RoutingDataSource dataSource() {
        RoutingDataSource dynamicDataSource = new RoutingDataSource();
        Map<Object, Object> targetDataSources = Maps.newHashMap();
        targetDataSources.put("one", oneDataSource());
        targetDataSources.put("two", twoDataSource());
        dynamicDataSource.setTargetDataSources(targetDataSources);

        DbContextHolder.supportList.addAll(targetDataSources.keySet());

        return dynamicDataSource;
        }
        }

        我是通过JPA Repository进行数据访问的,而Repository好像是在项目启动的时候就实例化好的。所以是不是因为这个所以切换不会起作用。
        简单的土豆:发下数据源配置,我看看。

      本文标题:在Spring Boot中配置多数据源&使用动态数据源

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