SpringBoot多数据源配置(hikari)

SpringBoot 2.0+ 开始推 HikariCP ,将默认的数据库连接池从 tomcat jdbc pool 改为了 hikari , HikariCP 在性能和并发方面表现更好一些

yml配置:

#数据源配置
 datasource:
   dsa:
     driver-class-name: com.sybase.jdbc4.jdbc.SybDataSource
     jdbc-url: jdbc:sybase:Tds:127.0.0.1:5127/test
     type: com.zaxxer.hikari.HikariDataSource
     username: root
     password: root
   dsb:
     driver-class-name: com.sybase.jdbc4.jdbc.SybDataSource
     jdbc-url: jdbc:sybase:Tds:127.0.0.1:5127/test
     type: com.zaxxer.hikari.HikariDataSource
     username: root
     password: root

com.zaxxer.hikari.HikariDataSource 包为mybatis自带
导入以下依赖

org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.1

1.创建DBProperties



import com.zaxxer.hikari.HikariDataSource;

import lombok.Data;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.stereotype.Component;

/**

* 实际数据源配置

*/

@Component

@Data

@ConfigurationProperties(prefix ="spring.datasource")

public class DBProperties {

private HikariDataSourcedsa;

 private HikariDataSourcedsc;

 private HikariDataSourcedsb;

}

2.创建dataSource

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

import java.util.HashMap;

import java.util.Map;

/**

* 数据源配置

*/

@Configuration

@EnableScheduling

@Slf4j

public class DataSourceConfig {

@Autowired

  private DBPropertiesproperties;

  @Bean(name ="dataSource")

public DataSourcedataSource() {

//按照目标数据源名称和目标数据源对象的映射存放在Map中

      Map targetDataSources =new HashMap<>();

      targetDataSources.put("dsa", properties.getDsa());

      targetDataSources.put("dsb", properties.getDsb());

      targetDataSources.put("dsc", properties.getDsc());

      //采用是想AbstractRoutingDataSource的对象包装多数据源

      DynamicDataSource dataSource =new DynamicDataSource();

      dataSource.setTargetDataSources(targetDataSources);

      dataSource.setDefaultTargetDataSource(properties.getDsb());

      return dataSource;

  }

@Bean

  public PlatformTransactionManagertxManager() {

return new DataSourceTransactionManager(dataSource());

  }

}

3.创建DynamicDataSource

import lombok.extern.slf4j.Slf4j;

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

/**

* 动态数据源实现类

*/

@Slf4j

public class DynamicDataSourceextends AbstractRoutingDataSource {

//数据源路由,此方用于产生要选取的数据源逻辑名称

  @Override

  protected ObjectdetermineCurrentLookupKey() {

//从共享线程中获取数据源名称

      return DynamicDataSourceHolder.getDataSource();

  }

}

4.创建DynamicDataSourceHolder

/**

* 动态数据源持有者,负责利用ThreadLocal存取数据源名称

*/

public class DynamicDataSourceHolder {

/**

* 本地线程共享对象

*/

  private static final ThreadLocalTHREAD_LOCAL =new ThreadLocal<>();

  public static void putDataSource(String name) {

THREAD_LOCAL.set(name);

  }

public static StringgetDataSource() {

return THREAD_LOCAL.get();

  }

public static void removeDataSource() {

THREAD_LOCAL.remove();

  }

}

5.创建TargetDataSource

import java.lang.annotation.*;

/**

* 目标数据源注解,注解在方法上指定数据源的名称

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

public @interface TargetDataSource {

Stringvalue();//此处接收的是数据源的名称

}

6.创建DataSourceAspect

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.aspectj.lang.reflect.MethodSignature;

import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**

* 数据源AOP切面定义

*/

@Component

@Aspect

@Slf4j

public class DataSourceAspect {

//切换放在mapper接口的方法上,所以这里要配置AOP切面的切入点

  @Pointcut("execution( * com.wondersgroup.yilian.largescreen_interface.dao.*.*(..))")

public void dataSourcePointCut() {

}

@Before("dataSourcePointCut()")

public void before(JoinPoint joinPoint) {

Object target = joinPoint.getTarget();

      String method = joinPoint.getSignature().getName();

      Class[] clazz = target.getClass().getInterfaces();

      Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();

      try {

Method m = clazz[0].getMethod(method, parameterTypes);

        //如果方法上存在切换数据源的注解,则根据注解内容进行数据源切换

        if (m !=null && m.isAnnotationPresent(TargetDataSource.class)) {

TargetDataSource data = m.getAnnotation(TargetDataSource.class);

            String dataSourceName = data.value();

            DynamicDataSourceHolder.putDataSource(dataSourceName);

            //log.debug("current thread " + Thread.currentThread().getName() + " add " + dataSourceName + " to ThreadLocal");

        }else {

//log.debug("switch datasource fail,use default");

        }

}catch (Exception e) {

//log.error("current thread " + Thread.currentThread().getName() + " add data to ThreadLocal error", e);

      }

}

//执行完切面后,将线程共享中的数据源名称清空

  @After("dataSourcePointCut()")

public void after(JoinPoint joinPoint){

DynamicDataSourceHolder.removeDataSource();

  }

}

最后将自定义注解@TargetDataSource("dsa")根据不同的连接放在DAO层方法上。
(切记,如果在业务层加了事务,数据源将无法切换)

你可能感兴趣的:(SpringBoot多数据源配置(hikari))