Springboot多数据源

Springboot多数据源

SpringbootDurid多数据源

1. 添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.17</version>
        </dependency>

2. application配置

spring:
    datasource:
        primary:
            url: jdbc:mysql://127.0.0.1:3306/test001?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
            username: root
            password: 123456
            driver-class-name: com.mysql.cj.jdbc.Driver
            type: com.alibaba.druid.pool.DruidDataSource
        secondary:
            url:  jdbc:mysql://127.0.0.1:3306/test002?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
            username: root
            password: 123456
            driver-class-name: com.mysql.cj.jdbc.Driver
            type: com.alibaba.druid.pool.DruidDataSource
        druid:
            max-wait: 10000 #获取连接时最大等待时间,单位毫秒
            initial-size: 10 #初始化时建立物理连接的个数
            max-active: 100 #最大连接池数量
            min-idle: 10 #最小连接数
            time-between-eviction-runs-millis: 3600000 #检测连接的间隔时间
            min-evictable-idle-time-millis: 300000 #连接的最小生存时间
            test-while-idle: true  #检测连接是否有效
            test-on-borrow: false #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
            validation-query: SELECT 1 #用来检测连接是否有效的sql
            filters: stat #监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
            stat-view-servlet:
                url-pattern: /druid/*
                reset-enable: true #允许清空统计数据
                login-username: root #监控后台管理账号和密码
                login-password: root
            web-stat-filter:
                url-pattern: /*
                exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
    jpa:
        database: mysql
        generate-ddl: true
        hibernate:
            ddl-auto: create
            naming:
                physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        show-sql: true

3. 动态数据源

/**
 * 动态数据源
 * @author devcxl
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getContext();
    }

}

3. 数据源配置

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource primaryDataSource, DataSource secondaryDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put(DataSourceType.PRIMARY, primaryDataSource);
        targetDataSources.put(DataSourceType.SECONDARY, secondaryDataSource);
        return new DynamicDataSource(primaryDataSource, targetDataSources);
    }

    /**
     * 配置事务管理器,以便Spring事务管理可以处理多数据源
     */
    @Bean
    public PlatformTransactionManager transactionManager(DynamicDataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

4. SpringAOP切面配置

切换数据库上下文

/**
 * @author devcxl
 */
public class DynamicDataSourceContextHolder {

    private static final ThreadLocal<DataSourceType> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setContext(DataSourceType dataSourceType) {
        CONTEXT_HOLDER.set(dataSourceType);
    }

    public static DataSourceType getContext() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearContext() {
        CONTEXT_HOLDER.remove();
    }
}

AOP配置

/**
 * 用于处理数据源注解切换逻辑
 * @author devcxl
 */
@Aspect
@Component
public class DataSourceAspect {

    @Around("@annotation(ds)")
    public Object around(ProceedingJoinPoint point, DataSource ds) throws Throwable {
        try {
            DynamicDataSourceContextHolder.setContext(ds.value());
            return point.proceed();
        } finally {
            DynamicDataSourceContextHolder.clearContext();
        }
    }
}

其他相关