springboot配置多数据源

本文介绍在 Spring Boot 中如何通过 AOP 实现多数据源的动态切换,包括依赖配置、数据源设置及注解的自定义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这两天的学习得知,springboot配置多数据源可以分为两种方式,一种是分包的形式,一种是基于aop的形式。各有优缺点,看自己了。今天简单来实现一下基于aop的形式。
首先是我的依赖

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
		   <groupId>org.springframework.boot</groupId>
		   <artifactId>spring-boot-starter-test</artifactId>
		</dependency>
		<!-- Web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 热部署 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<!-- lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
        
	 	<!-- MySql驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<!-- 数据源 -->
		<dependency>
		   <groupId>com.alibaba</groupId>
		   <artifactId>druid-spring-boot-starter</artifactId>
		   <version>1.1.10</version>
		</dependency>
		
	      <!-- AOP -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		
		<dependency>
	      <groupId>org.springframework</groupId>
	      <artifactId>spring-jdbc</artifactId>
		</dependency>
		
		<dependency>
		    <groupId>org.mybatis.spring.boot</groupId>
		    <artifactId>mybatis-spring-boot-starter</artifactId>
		    <version>2.1.3</version>
		</dependency>

接下来是我的数据库配置信息

spring:
    #数据库配置      
  datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://127.0.0.1:3306/ljw?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&allowMultiQueries=true
                username: root
                password: root
            # 从库数据源
            slave:
                url: jdbc:mysql://175.24.234.186:3306/ljw?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&allowMultiQueries=true
                username: root
                password: 123456

要实现多数据源,那么我们可以利用spring提供的预留接口去处理->AbstractRoutingDataSource

贴上我们的数据源配置类

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

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 com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;

/**
 * 数据源配置类
 * @author ljw
 *
 */
@Configuration
public class DruidConfig{
	
	/**
	 * 主数据源
	 * @return
	 */
    @Bean(name="masterDataSource")
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(){
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return dataSource;
    }

    /**
     * 从数据源
     * @return
     */
    @Bean(name="slaveDataSource")
    @ConfigurationProperties("spring.datasource.druid.slave")
    public DataSource slaveDataSource(){
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return dataSource;
    }

    /**
     * 动态数据源配置
     * @param masterDataSource
     * @param slaveDataSource
     * @return
     */
    @Bean(name = "dynamicDataSource")
    @Primary
    public DataSource dynamicDataSource (@Qualifier(value="masterDataSource") DataSource masterDataSource,@Qualifier(value="slaveDataSource") DataSource slaveDataSource){
    	//设置默认数据源
    	DynamicDataSource dd = new DynamicDataSource();
        dd.setDefaultTargetDataSource(masterDataSource);
        //多数据源配置
    	Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterDataSource);
        targetDataSources.put("slave", slaveDataSource);
        dd.setTargetDataSources(targetDataSources);
        return dd;
    }
}

这里动态去获取数据源

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

public class DynamicDataSource extends AbstractRoutingDataSource{

	@Override
	protected Object determineCurrentLookupKey() {
		System.err.println("数据源为:"+DataSourceContextSupport.get());
		return DataSourceContextSupport.get();
	}
}

为了保证线程安全,我们使用ThreadLocal去存储数据源的key

import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * @author ljw
 */
@Component
public class DataSourceContextSupport {

    public static final ThreadLocal<String> dataContext = new ThreadLocal<>();

    private static final String dataType = "master";//默认走主库

    /**
     * 设置当前信息
     */
    public static void set(String type) {
        dataContext.set(type);
    }

    /**
     * 获取当前数据信息
     */
    public static String get() {
        return Optional.ofNullable(dataContext.get()).orElse(dataType);
    }

    /**
     * 移除当前数据信息
     */
    public static void remove() {
        dataContext.remove();
    }
}

由于我们是自定义数据源,所以我们在启动的时候要移除默认的

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MpApplication {

	public static void main(String[] args) {
		SpringApplication.run(MpApplication.class, args);
	}
}

此时我们启动项目来看一下效果,默认走的是主数据源,和我们的配置对应
在这里插入图片描述
那么如何实现切换数据源呢?

要实现切换数据源,我们可以先自定义一个注解DataSource 默认主数据源

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 指定数据源注解
 * @author ljw
 *
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource{
    /**
     * 默认主数据源
     */
    public String value() default "master";
}

在执行前设置当前数据源

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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;



/**
 * 多数据源切面管理
 * @author ljw
 *
 */
@Aspect
@Order(1)
@Component
public class DataSourceAspect{
	
	 //切入点
    @Pointcut("@annotation(com.spring.framework.config.DataSource)")
    public void pointCut(){}
    
    
    @Before("pointCut()")
    public void doBefore(JoinPoint point) throws Throwable{
    	Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null){
        	if(method.getAnnotation(DataSource.class)!=null) {
        		DataSource datasource = method.getAnnotation(DataSource.class);
        		String value = datasource.value();
        		DataSourceContextSupport.set(value);
        	}
        }
    }
    
    @After("pointCut()")
    public void doAfter(JoinPoint point) throws Throwable{
    	DataSourceContextSupport.remove();
    }
}

看一下效果
在这里插入图片描述
简单的配置到这里就结束了,至于事务问题在这先不做讨论。小伙伴可以简单了解一下多数据源如何配置即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值