在项目遇到多数据源的问题,主要是针对部分数据需要单独处理应用场景;

1.本次项目配置基于springboot+mybatis+maven集成的,首先在yml配置相关如下:其中需要注意单数据源是url,多数据源要改成 jdbc-url,否则会报异常(Error querying database.  Cause: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName)

server:
  port: 8081

spring:
  datasource:
    database1:
      jdbc-url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
    database2:
      jdbc-url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver

#mybatis config
mybatis:
  mapper-locations: classpath*:mapper/*/*.xml

  2.配置好了,需要在启动类先加上@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})这个类位置:

import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
3.因为需要用到springboot的aop所以需要导包,在pom.xml文件导入
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

 4.多数据源的结构以下:

springboot注解配置多数据源

 

 内容直接给大家展示:

1.DataSourceAspect
package com.example.demo.config.db.dataSource;
 

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 lxp
 * @create 2021-12-28 12:15
 **/
@Aspect
@Component
@Slf4j
// 优先级, 1标识最先执行
@Order(1)
public class DataSourceAspect {
    @Pointcut("execution(* com.example.demo.mapper..*.*(..)))")
    public void dataSourcePoint() {}
 
    @Before("dataSourcePoint()")
    public void before(JoinPoint joinPoint) {
        Object target = joinPoint.getTarget();
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        // 执行方法名
        String methodName = methodSignature.getName();
        // 方法参数
        Class[] parameterTypes = methodSignature.getParameterTypes();
        try {
            // 获取方法, 直接getClass获取对象可能为代理对象
            Method method = target.getClass().getInterfaces()[0].getMethod(methodName, parameterTypes);
            // 添加默认数据源
            String dataSource = DataSourceType.Master.getName();
            if (null != method && method.isAnnotationPresent(MyDataSource.class)) {
                MyDataSource targetDataSource = method.getAnnotation(MyDataSource.class);
                dataSource = targetDataSource.value().getName();
            }
            // 此处添加线程对应的数据源到上下文
            // 在AbstractRoutingDataSource子类中拿到数据源, 加载后进行配置
            JdbcContextHolder.putDataSource(dataSource);
            log.info("generate data source : " + dataSource);
        } catch (Exception e) {
            log.info("error", e);
        }
 
    }
 
    /**
     * 清除数据源, 方法执行完成后, 清除数据源
     */
    @After("dataSourcePoint()")
    public void after(JoinPoint joinPoint) {
        JdbcContextHolder.clear();
    }
 
}

2.DataSourceConfig

package com.example.demo.config.db.dataSource;

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 {

    @Bean(name =  "database1")
    @ConfigurationProperties(prefix = "spring.datasource.database1")
    public DataSource dataSource1() {
        //database1数据源
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "database2")
    @ConfigurationProperties(prefix = "spring.datasource.database2")
    public DataSource dataSource2() {
        //database2数据源
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name="dynamicDataSource")
    @Primary    //优先使用,多数据源
    public DataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 设置默认数据源为first数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());
        // 配置多数据源,
        // 添加数据源标识和DataSource引用到目标源映射
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(DataSourceType.Master.getName(), dataSource1());
        dataSourceMap.put(DataSourceType.Slave.getName(), dataSource2());
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        return dynamicDataSource;

    }
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

}

3.DataSourceType

package com.example.demo.config.db.dataSource;

public enum DataSourceType {

    Master("database1"),
    Slave("database2");
    private String name;
    private DataSourceType(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4.DynamicDataSource

package com.example.demo.config.db.dataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;


public class DynamicDataSource extends AbstractRoutingDataSource {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Override
    protected Object determineCurrentLookupKey() {
        logger.info("数据源为{}",JdbcContextHolder.getDataSource());
        return JdbcContextHolder.getDataSource();
    }
    
}
View Code

相关文章:

  • 2021-06-28
  • 2022-01-24
  • 2021-12-14
猜你喜欢
  • 2021-11-19
  • 2021-06-21
  • 2021-07-04
  • 2021-09-07
相关资源
相似解决方案