1. 程式人生 > 程式設計 >spring boot多資料來源動態切換程式碼例項

spring boot多資料來源動態切換程式碼例項

這篇文章主要介紹了spring boot多資料來源動態切換程式碼例項,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

當專案中存在多資料來源時,就涉及到資料來源的動態切換,通過研究,特此記錄一下。

1、maven依賴

<!--資料庫連線-->
<dependency>
      <groupId>com.oracle</groupId>
      <artifactId>ojdbc6</artifactId>
      <version>11.2.0.4</version>
      <scope>runtime</scope>
    </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-jdbc</artifactId>
    </dependency>
<!--aop->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

2、多資料來源資訊配置

#多資料來源測試
spring:
 datasource:
  druid:
   master:
    driver-class-name: oracle.jdbc.driver.OracleDriver
    username: test
    password: test
    url: jdbc:oracle:thin:@//ip1:1521/orcl
   slave:
    driver-class-name: oracle.jdbc.driver.OracleDriver
    username: test
    password: test
    url: jdbc:oracle:thin:@//ip2:1521/orcl

3、資料來源配置資訊轉換成實體類

@ConfigurationProperties(prefix = "spring.datasource.druid")
@Data
@Component
public class DataSourceProperties {
  private Map<String,String>master;
  private Map<String,String>slave;
}

4、動態資料來源切換類

public class DynamicDataSource extends AbstractRoutingDataSource {

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

  public DynamicDataSource(DataSource defaultTargetDataSource,Map<Object,Object> 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();
  }
}

5、多資料來源配置類

@Configuration
public class DynamicDataSourceConfig {

  @Bean
  public DataSource master(@Autowired DataSourceProperties dataSourceProperties){
    DruidDataSource druidDataSource = new DruidDataSource();
    Map<String,String> master = dataSourceProperties.getMaster();
    druidDataSource.setUsername(master.get("username"));
    druidDataSource.setPassword(master.get("password"));
    druidDataSource.setUrl(master.get("url"));
    //其他引數配置 省略
    return druidDataSource;
  }

  @Bean
  public DataSource slave(@Autowired DataSourceProperties dataSourceProperties){
    DruidDataSource druidDataSource = new DruidDataSource();
    Map<String,String> slave = dataSourceProperties.getSlave();
    druidDataSource.setUsername(slave.get("username"));
    druidDataSource.setPassword(slave.get("password"));
    druidDataSource.setUrl(slave.get("url"));
    //其他引數配置 省略
    return druidDataSource;
  }

  @Bean
  @Primary
  public DynamicDataSource dataSource(DataSource master,DataSource slave){
    Map<Object,Object>map = new HashMap<>(4);
    map.put("master",master);
    map.put("slave",slave);
    return new DynamicDataSource(master,map);
  }
}

6、自定義@DataSource註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {

  String name() default "master";
}

7、Aop切面類配置

@Component
@Aspect
public class DataSourceAspect {

  @Pointcut("@annotation(com.zxgeo.sso.muiltDatasource.anons.DataSource)")
  public void dataSourcePointCut(){}

  @Around(value = "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("master");
    }else {
      DynamicDataSource.setDataSource(dataSource.name());
    }
    try {
      return point.proceed();
    } finally {
      DynamicDataSource.clearDataSource();
    }
  }
}

8、啟動配置註解資訊,重要(不然執行會報錯)

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})

9、測試

(1)、service層(此處沒有使用mybatis)

@Service
public class TestService {

  @Autowired
  private javax.sql.DataSource dataSource;

  @DataSource
  public Map<String,Object> getMasterDataSource() throws SQLException {
    Connection connection = dataSource.getConnection();
    Map<String,Object> map;
    try (PreparedStatement preparedStatement
           = connection.prepareStatement("SELECT * FROM AA WHERE A=10001")) {
      ResultSet resultSet = preparedStatement.executeQuery();
      map = new HashMap<>();
      while (resultSet.next()){
        map.put("A",resultSet.getString("A"));
        map.put("B",resultSet.getString("B"));
        map.put("C",resultSet.getString("C"));
      }
    }
    return map;
  }
  @DataSource(name = "slave")
  public Map<String,Object> getSlaveDataSource() throws SQLException {
    Connection connection = dataSource.getConnection();
    Map<String,Object> map;
    try (PreparedStatement preparedStatement
           = connection.prepareStatement("SELECT * FROM AA WHERE A=10002")) {
      ResultSet resultSet = preparedStatement.executeQuery();
      map = new HashMap<>();
      while (resultSet.next()){
        map.put("A",resultSet.getString("C"));
      }
    }
    return map;
  }
}

(2)、單元測試

@SpringBootTest
@RunWith(SpringRunner.class)
class SsoApplicationTests {

  @Autowired
  private TestService testService;

  @Test
  public void muliDatasorce() throws SQLException {
    Map<String,Object> masterDataSourceUrl = testService.getMasterDataSource();
    System.out.println(masterDataSourceUrl);
    Map<String,Object> slaveDataSourceUrl = testService.getSlaveDataSource();
    System.out.println(slaveDataSourceUrl);
  }
}

(3)、結果:

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。