springboot注解配置多数据源
在项⽬遇到多数据源的问题,主要是针对部分数据需要单独处理应⽤场景;
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: sql.jdbc.Driver
database2:
jdbc-url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8
username: root
password: 123456
driver-class-name: sql.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所以需要导包,在l⽂件导⼊
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
 4.多数据源的结构以下:
内容直接给⼤家展⽰:
1.DataSourceAspect
fig.db.dataSource;
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.flect.MethodSignature;
import annotation.Order;
import org.springframework.stereotype.Component;
import flect.Method;
/**
* 多数据源配置, 配置
* @author lxp
* @create 2021-12-28 12:15
**/
@Aspect
@Component
@Slf4j
// 优先级, 1标识最先执⾏
@Order(1)
public class DataSourceAspect {
@Pointcut("execution(* ample.demo.mapper..*.*(..)))")
public void dataSourcePoint() {}
@Before("dataSourcePoint()")
public void before(JoinPoint joinPoint) {
Object target = Target();
MethodSignature methodSignature = (Signature();
// 执⾏⽅法名
String methodName = Name();
// ⽅法参数
Class[] parameterTypes = ParameterTypes();
try {
// 获取⽅法, 直接getClass获取对象可能为代理对象
Method method = Class().getInterfaces()[0].getMethod(methodName, parameterTypes);
// 添加默认数据源
String dataSource = Name();
if (null != method && method.isAnnotationPresent(MyDataSource.class)) {
MyDataSource targetDataSource = Annotation(MyDataSource.class);
dataSource = targetDataSource.value().getName();
}
// 此处添加线程对应的数据源到上下⽂
/
/ 在AbstractRoutingDataSource⼦类中拿到数据源, 加载后进⾏配置
JdbcContextHolder.putDataSource(dataSource);
log.info("generate data source : " + dataSource);
} catch (Exception e) {
log.info("error", e);
}
}
/**
* 清除数据源, ⽅法执⾏完成后, 清除数据源
*/
springboot和过滤器
@After("dataSourcePoint()")
public void after(JoinPoint joinPoint) {
JdbcContextHolder.clear();
}
}
2.DataSourceConfig
fig.db.dataSource;
import org.t.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder;
import t.annotation.Bean;
import t.annotation.Configuration;
import t.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import ansaction.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数据源
ate().build();
}
@Bean(name = "database2")
@ConfigurationProperties(prefix = "spring.datasource.database2")
public DataSource dataSource2() {
//database2数据源
ate().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(Name(), dataSource1());        dataSourceMap.put(Name(), dataSource2());        dynamicDataSource.setTargetDataSources(dataSourceMap);
return dynamicDataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
3.DataSourceType
fig.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
fig.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 = Class());
@Override
protected Object determineCurrentLookupKey() {
logger.info("数据源为{}",DataSource());
DataSource();
}
}
View Code
5.JdbcContextHolder
fig.db.dataSource;
/**
* 动态数据源的上下⽂ threadlocal
*/
public class JdbcContextHolder {
private final static ThreadLocal<String> local = new ThreadLocal<>();
public static void putDataSource(String name) {
local.set(name);
}
public static String getDataSource() {
();
}
/**
* 清除数据源
*/
public static void clear() {
}
}
View Code
6.MyDataSource
fig.db.dataSource;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 数据源选择--⾃定义注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyDataSource {
DataSourceType value();    //默认主表
}
View Code
最后应⽤就⽐较简单了,默认情况有默认的数据库源,需要调⽤别的就加注解即可
最后通过调⽤接⼝可以看到数据是不同数据库的数据,完整的过程基本都有,多数据源要把dao层和xml⽂件隔离开更好的区分