springBoot动态数据源切换、自定义注解的配置和使用

一、主要配置类列表展示
在这里插入图片描述

  外加一个配置类DynamicDataSourceConfig.java

二、配置文件例如application-test.yml

spring:
  # 数据源配置
  datasource:
    # 连接池配置
    druid:
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: xxx
        password: xxx
        url: jdbc:mysql://xxx.xxx.xxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
        initialSize: 5
        minIdle: 5
        maxActive: 20
      db2:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: xxx
        password: xxx
        url: jdbc:mysql://xxx.xxx.xxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
        initialSize: 5
        minIdle: 5
        maxActive: 20
  servlet:
    multipart:
      max-file-size: 8MB
      max-request-size: 8MB

三、DBTypeEnum

/**
 * @author :cw
 * @date :Created in 2020/6/10 下午12:04
 * @description:
 * @modified By:
 * @version: $
 */

public enum DBTypeEnum {

    DB_ONE("db1"),
    DB_TWO("db2");
    
    private String value;

    DBTypeEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

四、DbContextHolder

/**
 * @author :cw
 * @date :Created in 2020/6/10 下午12:03
 * @description:
 * @modified By:
 * @version: $
 */

public class DbContextHolder {

    private static final ThreadLocal contextHolder = new ThreadLocal<>();
    /**
     * 设置数据源
     * @param dbTypeEnum
     */
    public static void setDbType(DBTypeEnum dbTypeEnum) {
        contextHolder.set(dbTypeEnum.getValue());
    }

    /**
     * 取得当前数据源
     * @return
     */
    public static String getDbType() {
        return (String) contextHolder.get();
    }

    /**
     * 清除上下文数据
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
}

五、DynamicDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
 * @author :cw
 * @date :Created in 2020/6/10 下午12:03
 * @description:
 * @modified By:
 * @version: $
 */

public class DynamicDataSource extends AbstractRoutingDataSource {
    /**
     * 取得当前使用哪个数据源
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DbContextHolder.getDbType();
    }
}

六、DBMapperConvert

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DBMapperConvert {
    String value() default "";
}

七、DataSourceSwitchAspect

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.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author :cw
 * @date :Created in 2020/6/10 下午12:12
 * @description:
 * @modified By:
 * @version: $
 */
@Component
@Aspect
@Order(1) //这是为了保证AOP在事务注解之前生效,Order的值越小,优先级越高
@Slf4j
public class DataSourceSwitchAspect {
    @Pointcut("@annotation(DBMapperConvert)")
    private void dbChoose() {
    }
    @Before("dbChoose()")
    public void convertDb(JoinPoint joinPoint) {
        MethodSignature methodSignature =  (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        DBMapperConvert annotation = method.getAnnotation(DBMapperConvert.class);
        String value = annotation.value();
        if(DBTypeEnum.DB_ONE.getValue().equals(value)){
            log.info("---------切换到 db1 数据源开始操作...:"+value);
            DbContextHolder.setDbType(DBTypeEnum.DB_ONE);
        }else(DBTypeEnum.DB_TWO.getValue().equals(value)){
            log.info("--------切换到 db2 数据源开始操作...:"+value);
            DbContextHolder.setDbType(DBTypeEnum.DB_TWO);
      }
    }
    @After("dbChoose()")
    public void afterPointcut(JoinPoint joinPoint) {
        MethodSignature methodSignature =  (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        DBMapperConvert annotation = method.getAnnotation(DBMapperConvert.class);
        String value = annotation.value();
        log.info("---------切换到 "+value+" 数据源操作结束...:"+value);
        DbContextHolder.c();
    }
}

八、DynamicDataSourceConfig

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

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

/**
 * @author :cw
 * @date :Created in 2020/6/10 上午11:56
 * @description:
 * @modified By:
 * @version: $
 */

@Configuration
public class DynamicDataSourceConfig {

    @Bean(name = "dbOne")
    @ConfigurationProperties(prefix = "spring.datasource.druid.db1" )
    public DataSource oneDb () {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "dbTwo")
    @ConfigurationProperties(prefix = "spring.datasource.druid.db2" )
    public DataSource twoDb () {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 动态数据源配置
     * @return
     */
    @Bean
    @Primary
    public DataSource multipleDataSource (@Qualifier("dbOne") DataSource dbOne,
                                          @Qualifier("dbTwo") DataSource dbTwo) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map< Object, Object > targetDataSources = new HashMap<>(2);
        targetDataSources.put(DBTypeEnum.DB_ONE.getValue(), dbOne );
        targetDataSources.put(DBTypeEnum.DB_TWO.getValue(), dbTwo);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(dbOne);
        return dynamicDataSource;
    }
}

九、使用方式

@Override
@DBMapperConvert("db1")
public UserPo getTest1(String id){
    UserPo userPo = dbOneMapper.getTest1(id);
    return userPo;
}

@Override
@DBMapperConvert("db2")
public UserPo getTest2(String id){
    UserPo userPo = dbTwoMapper.getTest2(id);
    return userPo;
}

到此即可实现简单数据源的切换操作,待补充数据源动态操作配置

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值