springboot整合druid(多数据源配置)

一、pom引入

 
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>1.1.10</version>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.1.10</version>
</dependency>

二、yml文件配置

multiple: true
spring:
  datasource:
    primary:
      hikari:
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: 1234ABcd
        type: com.alibaba.druid.pool.DruidDataSource
        jdbc-url: jdbc:mysql://192.168.30.132:23306/test1?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=true&allowMultiQueries=true
    secondary:
      hikari:
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: 1q2w3e4r5t
        type: com.alibaba.druid.pool.DruidDataSource
        jdbc-url: jdbc:mysql://192.168.30.136:43306/test2?characterEncoding=utf-8&serverTimezone=Hongkong&useSSL=true&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
    druid:
      initial-size: 10
      min-idle: 10
      max-active: 100
      max-wait: 60000
      time-between-eviction-runs-millis: 2000
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: false
      max-pool-prepared-statement-per-connection-size: 20
      use-global-data-source-stat: true

三、DataSourceName注解


import java.lang.annotation.*;


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface DataSourceName {

    /**
     * 指定数据源名称
     * @return dataSourceName
     */
    String value() default "primary";
}

四、DynamicDataSourceAspect

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class DynamicDataSourceAspect {

    @Before("@annotation(dataSourceName)")
    public void beforeSwitchDataSource(DataSourceName dataSourceName){
        // 切换数据源
        DataSourceNameContextHolder.setDataSourceName(dataSourceName.value());
    }

    @After("@annotation(com.sgcc.dlsc.pxsettelementinfpubquery.config.DB.DataSourceName)")
    public void afterSwitchDataSource(){
        DataSourceNameContextHolder.resetDataSourceName();
    }
}

五、DynamicDataSourceRouter

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

import java.io.PrintWriter;
import java.sql.SQLException;


public class DynamicDataSourceRouter extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceNameContextHolder.getDataSourceName();
    }

    @Override
    public void setLogWriter(PrintWriter pw) throws SQLException {
        super.setLogWriter(pw);
    }
}

六、DataSourceConfig


import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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


@Configuration
// 自定义数据源一定要排除SpringBoot自动配置数据源,不然会出现循环引用的问题,The dependencies of some of the beans in the application context form a cycle
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
@ConditionalOnProperty(name = "multiple",havingValue = "true")
public class DataSourceConfig {


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

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

    /**
     * 动态数据源
     * 通过AOP+注解实现动态切换
     *
     * @return
     */
    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dataSource() {
        DynamicDataSourceRouter dynamicDataSource = new DynamicDataSourceRouter();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(primaryDataSource());
        // 配置多数据源
        Map<Object, Object> dataSourceMap = new HashMap(5);
        dataSourceMap.put("primary", primaryDataSource());
        dataSourceMap.put("secondary", secondaryDataSource());
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    /**
     * 配置@Transactional注解事物
     *
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

}

七、DataSourceNameContextHolder

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.NamedThreadLocal;


@Slf4j
public class DataSourceNameContextHolder {

    private static final ThreadLocal<String> dataSourceNameContextHolder = new NamedThreadLocal<>("DataSourceContext");

    /** 默认数据源名称 */
    public static final String DEFAULT_DATASOURCE_NAME = "primary";

    public static void setDataSourceName(String dataSourceName) {
        log.info("切换到[{}]数据源", dataSourceName);
        dataSourceNameContextHolder.set(dataSourceName);
    }

    public static String getDataSourceName() {

        return dataSourceNameContextHolder.get() != null ? dataSourceNameContextHolder.get() : DEFAULT_DATASOURCE_NAME;
    }

    public static void resetDataSourceName() {
        dataSourceNameContextHolder.remove();
    }
}

八、切换数据源

DataSourceNameContextHolder.setDataSourceName("secondary");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值