ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Springboot实现配置多数据源

2026/8/13 9:24:35 拓冰建站 浏览量
Springboot实现配置多数据源

一、前言
在实际开发应用中,我们可能需要在一个项目中连接多个数据源,已满足实际的开发业务需求,那么就需要实现连接多数据源的功能,而一些框架和工具,如Spring Boot和MyBatis等,提供了对多数据源的支持,简化了多数据源的配置和管理过程。

二、Spring Boot 如何配置多数据源?
1.在pom.xml中添加相应的数据库驱动和Spring Boot的数据库依赖,比如Postgresql、Mysql等。
以Postgresql为例:

        <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.9</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency>

2.在application.properties或application.yml配置文件中添加多个数据源的连接信息。

#主数据源
spring.datasource.primary.url = jdbc:postgresql://localhost:5432/test
spring.datasource.primary.username = postgres
spring.datasource.primary.password = 123456
spring.datasource.primary.driver-class-name = org.postgresql.Driver
spring.datasource.primary.type = com.alibaba.druid.pool.DruidDataSource#拓展数据源
spring.datasource.de.url = jdbc:postgresql://localhost:5432/test1
spring.datasource.de.username = postgres
spring.datasource.de.password = 123456
spring.datasource.de.driver-class-name = org.postgresql.Driver
spring.datasource.de.type = com.alibaba.druid.pool.DruidDataSource

3.创建数据源bean
在Spring Boot的配置类中创建多个数据源的DataSource Bean,并注入对应的配置信息。

import com.alibaba.druid.pool.DruidDataSource;
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Bean(name = "primary")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource dataSourcePrimary() {return new DruidDataSource() ;}@Bean(name = "de")@ConfigurationProperties(prefix = "spring.datasource.de")public DataSource dataSourceDe() {return new DruidDataSource();}@Bean("dynamicDataSource")@Primarypublic DataSource dynamicDataSource (@Qualifier("primary") DataSource primary, @Qualifier("dbMap") DataSourceMap dbMap) {DynamicDataSource dynamicDataSource = new DynamicDataSource() ;dynamicDataSource.setDefaultTargetDataSource(primary);dynamicDataSource.setTargetDataSources(dbMap.getDbMap());return dynamicDataSource ;}@Beanpublic PlatformTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

DynamicDataSource 实现类:

import com.smartcitysz.dp.report.util.DataSourceUtil;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceUtil.getDB();}
}

DataSourceMap实现类:

import lombok.Data;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;@Component("dbMap")
@Data
public class DataSourceMap  {private Map dbMap ;public DataSourceMap(@Qualifier("primary") DataSource primary, @Qualifier("de")DataSource de) {this.dbMap = new HashMap<>() ;this.dbMap.put("primary",primary) ;this.dbMap.put("de",de) ;}public Map<Object, Object> getDbMap() {return dbMap;}public void setDbMap(Map<Object, Object> dbMap) {this.dbMap = dbMap;}
}

DataSourceUtil工具类:

public class DataSourceUtil {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>() ;/*** 设置数据源名* @param dbType*/public static void setDB(String dbType) {contextHolder.set(dbType);}public static String getDB() {return contextHolder.get() ;}public static void clearDB() {contextHolder.remove();}}

4.接着实现一个多数据源切面。

import com.smartcitysz.dp.report.aop.annotation.CurDataSource;
import com.smartcitysz.dp.report.util.DataSourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** 多数据源切面处理类*/
@Slf4j
@Aspect
@Component
public class DataSourceAspect implements Ordered {private static String PRIMARY = "primary";@Pointcut("@annotation(com.smartcitysz.dp.report.aop.annotation.CurDataSource)")public void dataSourcePointCut() {}@Around("dataSourcePointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();CurDataSource ds = method.getAnnotation(CurDataSource.class);log.info("around:{}",ds.name());if (ds == null) {DataSourceUtil.setDB(PRIMARY);log.info("set datasource is " + PRIMARY);} else {DataSourceUtil.setDB(ds.name());log.info("set datasource is " + ds.name());}try {return point.proceed();} finally {DataSourceUtil.clearDB();log.debug("clean datasource");}}@Overridepublic int getOrder() {return 1;}
}

多数据源注解类:

import java.lang.annotation.*;/*** 多数据源注解*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurDataSource {String name() default "";
}

最后只需要在方法上添加注解就可以实现不同数据源直接的切换了。