1、src/main/resources/application.properties 中配置好多个数据源

  spring.datasource.initialize=false
  #接口请求端口号、路径
  server.port=9090
  servcer.context-path=/
  #mybatis配置
  #mybatis.config-locations=classpath:mybatis/mybatis-config.xml
  mybatis.mapper-locations=classpath:mapper/*.xml
  #oracle数据库数据源信息
  oracle.datasource.driverClassName=oracle.jdbc.OracleDriver
  oracle.datasource.url=jdbc:oracle:thin:@ip/dbname
  oracle.datasource.username=user
  oracle.datasource.password=pwd
  #mysql数据库数据源信息
  mysql.datasource.jdbc.driverClassName=com.mysql.jdbc.Driver
  mysql.datasource.jdbc.url=jdbc:mariadb://ip:3306/dbname
  mysql.datasource.jdbc.username=user
  mysql.datasource.jdbc.password=pwd

2、定义一个枚举类型 DatabaseType.java,表示不同的环境

  package com.twf.springBootDemo.util;

/**
 * @author tianwf
 * @date 2020/12/30 9:58
 * oracle oracle数据库环境
 * mysql mysql数据库环境
 */
public enum DatabaseType {
    oracle("oracle", "1"), mysql("mysql", "2");

    private String name;
    private String value;

    DatabaseType(String name, String value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

3、定义一个 DatabaseContextHolder.java, 保存一个线程安全的DatabaseType容器

  package com.twf.springBootDemo.dataSourceConfig;

import com.twf.springBootDemo.util.DatabaseType;

/**
 * @author tianwf
 * @date 2020/12/30 10:00
 * 保存一个线程安全的DatabaseType容器
 */
public class DatabaseContextHolder {

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

    public static void setDatabaseType(DatabaseType databaseType) {
        contextHolder.set(databaseType);
    }

    public static DatabaseType getDatabaseType() {
        return contextHolder.get();
    }
}

4、定义动态数据源获取的方法 DynamicDataSource.java,集成 AbstractRoutingDataSource

  package com.twf.springBootDemo.dataSourceConfig;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @author tianwf
 * @date 2020/12/30 10:15
 * 动态数据源(需要继承AbstractRoutingDataSource)
 * 使用DatabaseContextHolder获取当前线程的DatabaseType
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DatabaseContextHolder.getDatabaseType();
    }
}

5、mybatis多数据源的配置 MybatisConfig.java

  package com.twf.springBootDemo.dataSourceConfig;

import com.alibaba.druid.pool.DruidDataSource;
import com.twf.springBootDemo.util.DatabaseType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author tianwf
 * @date 2020/12/30 10:21
 * mybatis多数据源的配置,springboot集成mybatis基本入口
 * 1、创建数据源
 * 2、创建SqlSessionFactory
 */

@Configuration
@MapperScan(basePackages = "com.twf.springBootDemo.mapper", sqlSessionFactoryRef = "sessionFactory")
public class MybatisConfig {
    /*mapper.xml路径*/
    @Value("${mybatis.mapper-locations}")
    private String mapperPath;

    /*oracle驱动*/
    @Value("${oracle.datasource.driverClassName}")
    private String oradbDriver;

    /*oracle数据库连接地址*/
    @Value("${oracle.datasource.url}")
    private String oraUrl;

    /*oracle数据库连接用户名*/
    @Value("${oracle.datasource.username}")
    private String oraUsername;

    /*oracle数据库连接密码*/
    @Value("${oracle.datasource.password}")
    private String oraPassword;

    /*mysql驱动*/
    @Value("${mysql.datasource.jdbc.driverClassName}")
    private String mysqldbDriver;

    /*mysql数据库连接地址*/
    @Value("${mysql.datasource.jdbc.url}")
    private String mysqlUrl;

    /*mysql数据库连接用户名*/
    @Value("${mysql.datasource.jdbc.username}")
    private String mysqlUsername;

    /*mysql数据库连接密码*/
    @Value("${mysql.datasource.jdbc.password}")
    private String mysqlPassword;

    /**
     * 创建 oracle环境 dataSource
     * @throws Exception
     */
    @Bean(name = "dataSourceOracle")
    public DataSource dataSourceOracle() throws Exception {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(oradbDriver);
        dataSource.setUrl(oraUrl);
        dataSource.setUsername(oraUsername);
        dataSource.setPassword(oraPassword);

        return dataSource;
    }

    /**
     * 创建 mysql环境 dataSource
     * @throws Exception
     */
    @Bean(name="dataSourceMysql")
    public DataSource dataSourceMysql() throws Exception {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(mysqldbDriver);
        dataSource.setUrl(mysqlUrl);
        dataSource.setUsername(mysqlUsername);
        dataSource.setPassword(mysqlPassword);

        return dataSource;
    }

    /**
     * 1、创建动态数据源
     * @throws Exception
     * @Primary该注解表示在同一个接口有多个类可以注入的时候,默认选择哪个,而不是让@Autowired报错
     */
    @Bean(name="dynamicDataSource")
    @Primary
    public DynamicDataSource dynamicDataSource(
            @Qualifier("dataSourceOracle") DataSource dataSourceOracle,
            @Qualifier("dataSourceMysql") DataSource dataSourceMysql
    ) throws Exception {
        Map<Object, Object> targetDataSource = new HashMap<>();
        targetDataSource.put(DatabaseType.oracle, dataSourceOracle);
        targetDataSource.put(DatabaseType.mysql, dataSourceMysql);
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSource);
        dynamicDataSource.setDefaultTargetDataSource(dataSourceOracle);

        return dynamicDataSource;
    }

    /**
     * 根据数据源创建SqlSessionFactory
     * @throws Exception
     */
    @Bean(name="sessionFactory")
    public SqlSessionFactory sessionFactory(
            @Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        PathMatchingResourcePatternResolver pmrpr = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(pmrpr.getResources(mapperPath));//*Mapper.xml位置

        return sqlSessionFactoryBean.getObject();
    }
}

6、修改服务类 StudentService.java:添加环境切换方法setDataSourceByEnvironment,同时在获取数据的方法中切换数据源

  package com.twf.springBootDemo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.twf.springBootDemo.dataSourceConfig.DatabaseContextHolder;
import com.twf.springBootDemo.entity.Customer;
import com.twf.springBootDemo.mapper.CustomerMapper;
import com.twf.springBootDemo.service.WebService;
import com.twf.springBootDemo.util.DatabaseType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@MapperScan("com.twf.springBootDemo.mapper")
public class WebServiceImpl implements WebService {

    @Resource
    private CustomerMapper customerMapper;

    public void setDataSourceByEnvironment(String environment) {
        //oracle数据源
        if(environment.equals(DatabaseType.oracle.getValue())) {
            DatabaseContextHolder.setDatabaseType(DatabaseType.oracle);
        } else if(environment.equals(DatabaseType.mysql.getValue())) {//mysql数据源
            DatabaseContextHolder.setDatabaseType(DatabaseType.mysql);
        }
    }

    @Override
    public String helloWorld(String params) {
        System.out.println("====" + params);
        setDataSourceByEnvironment("1");
        List<Customer> customerList = customerMapper.getCustomerList();
//        System.out.println(customerList.size());
        if(customerList.size() > 0) {
            for(int i = 0; i < customerList.size(); i++) {
                Customer customer = customerList.get(i);
                System.out.println(customer.getName());
            }
        }

        return result;
    }
}

7、SpringBoot配置多数据源,会引发循环引用问题

  修改方案:在Spring boot启动的时候排除DataSourceAutoConfiguration,并另外导入MyBatisConfig

  @Import({MybatisConfig.class})
  @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

 

posted on 2020-12-30 15:17  vofill-work  阅读(684)  评论(0编辑  收藏  举报