美文网首页SpringBoot学习
SpringBoot配置多数据源

SpringBoot配置多数据源

作者: weisen | 来源:发表于2018-11-27 14:43 被阅读0次

    开发一个SpringBoot2.0项目,能在方法中方便的切换数据库。

    一、引入依赖

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
    
            <!-- postgresql -->
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <version>42.0.0</version>
            </dependency>
    
           <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    

    二、application.yml中配置数据库信息

    spring:
      application:
        name: bd-its-deg-service
      datasource:
        druid:
          pgdw:
            url: jdbc:postgresql://192.168.235.3/dw?characterEncoding=utf-8
            username: root
            password: 123456#
            driverClassName: org.postgresql.Driver
            filters: stat
            maxActive: 100
            initialSize: 5
            maxWait: 60000
            minIdle: 20
            timeBetweenEvictionRunsMillis: 60000
            minEvictableIdleTimeMillis: 300000
            validationQuery: "SELECT 'x'"
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            maxOpenPreparedStatements: 60
            removeAbandoned: true
            removeAbandonedTimeout: 1800
            logAbandoned: true
          crawl:
            url: jdbc:postgresql://192.168.235.3/crawl?characterEncoding=utf-8
            username: root2
            password: 666666#
            driverClassName: org.postgresql.Driver
            filters: stat
            maxActive: 100
            initialSize: 5
            maxWait: 60000
            minIdle: 20
            timeBetweenEvictionRunsMillis: 60000
            minEvictableIdleTimeMillis: 300000
            validationQuery: "SELECT 'x'"
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            maxOpenPreparedStatements: 60
            removeAbandoned: true
            removeAbandonedTimeout: 1800
            logAbandoned: true
    

    三、生成对应的数据库bean类DynamicDataSourceConfiguration

    
    @MapperScan(basePackages = "cn.com.bluemoon.bd.service.its.deg.dao")
    @Configuration
    public class DynamicDataSourceConfiguration {
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.druid.pgdw")
        public DataSource dbPgdw() {
            return DruidDataSourceBuilder.create().build();
        }
    
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.druid.crawl")
        public DataSource dbCrawl() {
            return DruidDataSourceBuilder.create().build();
        }
    
    
        /**
         * 核心动态数据源
         *
         * @return 数据源实例
         */
        @Bean
        public DataSource dynamicDataSource() {
            DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
            dataSource.setDefaultTargetDataSource(dbPgdw());
            Map<Object, Object> dataSourceMap = new HashMap<>(4);
            dataSourceMap.put(DataSourceKey.DB_PGDW, dbPgdw());
            dataSourceMap.put(DataSourceKey.DB_CRAWL, dbCrawl());
            dataSource.setTargetDataSources(dataSourceMap);
            return dataSource;
        }
    
        @Bean
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dynamicDataSource());
            //此处设置为了解决找不到mapper文件的问题
            sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
            return sqlSessionFactoryBean.getObject();
        }
    
        @Bean
        public SqlSessionTemplate sqlSessionTemplate() throws Exception {
            return new SqlSessionTemplate(sqlSessionFactory());
        }
    
        /**
         * 事务管理
         *
         * @return 事务管理实例
         */
        @Bean
        public PlatformTransactionManager platformTransactionManager() {
            return new DataSourceTransactionManager(dynamicDataSource());
        }
    
    }
    
    

    四、配置一个枚举类,记录数据库名

    public enum DataSourceKey {
        DB_PGDW,
        DB_CRAWL
    }
    

    五、配置一个注解,方法中有该注解的会动态切换数据库

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RUNTIME)
    public @interface DataSource {
        DataSourceKey value() default DataSourceKey.DB_PGDW;
    }
    

    DynamicDataSourceAspect.java

    @Aspect
    @Order(-1)
    @Component
    public class DynamicDataSourceAspect {
        private static final Logger LOG = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
    
        /**
         * 执行方法前更换数据源
         *
         * @param joinPoint        切点
         * @param targetDataSource 动态数据源
         */
        @Before("@annotation(targetDataSource)")
        public void doBefore(JoinPoint joinPoint, DataSource targetDataSource) {
            DataSourceKey dataSourceKey = targetDataSource.value();
            if (dataSourceKey == DataSourceKey.DB_CRAWL) {
                LOG.info(String.format("设置数据源为  %s", DataSourceKey.DB_CRAWL));
                DynamicDataSourceContextHolder.set(DataSourceKey.DB_CRAWL);
            } else {
                LOG.info(String.format("使用默认数据源  %s", DataSourceKey.DB_PGDW));
                DynamicDataSourceContextHolder.set(DataSourceKey.DB_PGDW);
            }
        }
    
        /**
         * 执行方法后清除数据源设置
         *
         * @param joinPoint        切点
         * @param targetDataSource 动态数据源
         */
        @After("@annotation(targetDataSource)")
        public void doAfter(JoinPoint joinPoint, DataSource targetDataSource) {
            LOG.info(String.format("当前数据源  %s  执行清理方法", targetDataSource.value()));
            DynamicDataSourceContextHolder.clear();
        }
    
    }
    

    DynamicDataSourceContextHolder.java

    public class DynamicDataSourceContextHolder {
    
        private static final ThreadLocal<DataSourceKey> currentDatesource = new ThreadLocal<>();
    
        /**
         * 清除当前数据源
         */
        public static void clear() {
            currentDatesource.remove();
        }
    
        /**
         * 获取当前使用的数据源
         *
         * @return 当前使用数据源的ID
         */
        public static DataSourceKey get() {
            return currentDatesource.get();
        }
    
        /**
         * 设置当前使用的数据源
         *
         * @param value 需要设置的数据源ID
         */
        public static void set(DataSourceKey value) {
            currentDatesource.set(value);
        }
    
    }
    

    DynamicRoutingDataSource.java

    public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
        private static final Logger LOG = LoggerFactory.getLogger(DynamicRoutingDataSource.class);
        @Override
        protected Object determineCurrentLookupKey() {
            LOG.info("当前数据源:{}", DynamicDataSourceContextHolder.get());
            return DynamicDataSourceContextHolder.get();
        }
    }
    

    具体的类如下图所示


    image.png

    六、用法

    在service方法中添加上配置的注解

        @Override
        @DataSource(DataSourceKey.DB_PGDW)
        public String exportDataTable(String param) {
            log.info("切换数据源为PG dw库 测试是否被调用:" + param + ">>>>>>>>>" + param);
            // 切换数据源为PG dw库
           }
    

    当然,也可以不使用注解,可以在同一个方法中使用不同的数据库

            @Override
        public String exportDataTable(String param) {
                    DynamicDataSourceContextHolder.set(DataSourceKey.DB_PGDW);
            log.info("切换数据源为PG dw库 测试是否被调用:" + param + ">>>>>>>>>" + param);
            // 切换数据源为PG dw库
                    if(......){
                      DynamicDataSourceContextHolder.set(DataSourceKey.DB_CRAWL);
                    }
           }
    

    参考文章:https://blog.csdn.net/u013360850/article/details/78861442

    相关文章

      网友评论

        本文标题:SpringBoot配置多数据源

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