spring boot+mybatisplus 多数据源配置

pom.xml

<dependencies>
        <!-- springboot核心包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>
        <!-- springboot-aop包,AOP切面注解,Aspectd等相关注解 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.3.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- jdbcTemple  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.23</version>
        </dependency>
        
        <!-- 开发测试环境修改文件实时生效包,生产默认不使用 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- mysql数据库连接包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

application.yml

spring:
  datasource:
    primary:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbcUrl: jdbc:mysql://192.168.20.33:3306/adm_user?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: adm123
    second:
      jdbcUrl: jdbc:mysql://192.168.20.33:3306/adm_order?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: adm123
    hikari:
      minimum-idle: 10
      maximum-pool-size: 100
  messages:
    basename: messages-common,messages-user

DataSourceConfig

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
public class DataSourceConfig {
    
    

    /**
     * 数据源1
     * spring.datasource.db1 :application.properteis中对应属性的前缀
     * @return
     */
    @Bean(name = "datasource1")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource dataSource1() {
    
    
        return DataSourceBuilder.create().build();
    }

    /**
     * 数据源1
     * spring.datasource.db2 :application.properteis中对应属性的前缀
     * @return
     */
    @Bean(name = "datasource2")
    @ConfigurationProperties(prefix = "spring.datasource.second")
    public DataSource dataSource2() {
    
    
        return DataSourceBuilder.create().build();
    }

    /**
     * 动态数据源: 通过AOP在不同数据源之间动态切换
     * @return
     */
    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
    
    
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());
        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap();
        dsMap.put("datasource1", dataSource1());
        dsMap.put("datasource2", dataSource2());

        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }

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

DataSourceSwitch

import java.lang.annotation.*;

/**
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.METHOD})
@Documented
public @interface DataSourceSwitch {
    
    
    String value() default "datasource1";
}

DynamicDataSource

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

public class DynamicDataSource extends AbstractRoutingDataSource {
    
    
    @Override
    protected Object determineCurrentLookupKey() {
    
    
        System.out.println("数据源为"+DataSourceContextHolder.getDB());
        return DataSourceContextHolder.getDB();
    }
}

DataSourceContextHolder

public class DataSourceContextHolder {
    
    
    /**
     * 默认数据源
     */
    public static final String DEFAULT_DS = "datasource1";

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

    /**
     * 设置数据源名
     * @param dbType
     */
    public static void setDB(String dbType) {
    
    
        System.out.println("切换到{"+dbType+"}数据源");
        contextHolder.set(dbType);
    }

    /**
     * 获取数据源名
     * @return
     */
    public static String getDB() {
    
    
        return (contextHolder.get());
    }

    /**
     * 清除数据源名
     */
    public static void clearDB() {
    
    
        contextHolder.remove();
    }
}

DynamicDataSourceAspect 切面配置

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.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class DynamicDataSourceAspect {
    
    
    @Before("@annotation(com.admalltech.server.config.DataSourceSwitch)")
    public void beforeSwitchDS(JoinPoint point){
    
    
        //获得当前访问的class
        Class<?> className = point.getTarget().getClass();
        //获得访问的方法名
        String methodName = point.getSignature().getName();
        //得到方法的参数的类型
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
        String dataSource = DataSourceContextHolder.DEFAULT_DS;
        try {
    
    
            // 得到访问的方法对象
            Method method = className.getMethod(methodName, argClass);
            // 判断是否存在@DataSourceSwitch注解
            if (method.isAnnotationPresent(DataSourceSwitch.class)) {
    
    
                DataSourceSwitch annotation = method.getAnnotation(DataSourceSwitch.class);
                // 取出注解中的数据源名
                dataSource = annotation.value();
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        // 切换数据源
        DataSourceContextHolder.setDB(dataSource);
    }

    @After("@annotation(com.admalltech.server.config.DataSourceSwitch)")
    public void afterSwitchDS(JoinPoint point){
    
    
        DataSourceContextHolder.clearDB();
    }
}

service 注解使用

@Slf4j
@RequiredArgsConstructor
@Service
public class OrderService {
    
    
    @Autowired
    OrderMapper orderMapper;

    @DataSourceSwitch("datasource2")
    public List<Order> getList() {
    
    
        List<Order> list = orderMapper.selectList(new QueryWrapper<>());
        return list;
    }
}

接口不添加@DataSourceSwitch 默认使用datasource1

猜你喜欢

转载自blog.csdn.net/weixin_45818787/article/details/118670830