一、配置pom文件
<!-- 添加druid数据源 -->
<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>
二、动态数据源配置在yml文件
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
db1:
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: hqw19980127
url: jdbc:mysql://localhost:3306/course?useUnicode=true&characterEncoding=utf8
db2:
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: hqw19980127
url: jdbc:mysql://localhost:3306/track?useUnicode=true&characterEncoding=utf8
jpa:
show-sql: true
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
三、新建configuration的配置文件
@Configuration
@Component
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid.db1")
public DataSource db1DataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.db2")
public DataSource db2DataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource db1DataSource,
DataSource db2DataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("db1",db1DataSource);
targetDataSources.put("db2", db2DataSource);
return new DynamicDataSource(db1DataSource, targetDataSources);
}
}
四、数据源切换类
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
五、数据源注解(标注在dao层)
/**
* 备注:自定义数据源选择注解
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "";
}
六、配置aop,利用切面变成切换数据源
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.qingwen.mutidatasource.config.DataSource)") //注解切面
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
//注解在类上
DataSource classDataSource = point.getTarget().getClass().getAnnotation(DataSource.class);
//注解配置在mapper的方法上,可以重写放在Mapper.class上
if(classDataSource == null) {
DataSource dataSource = method.getAnnotation(DataSource.class);
if (dataSource == null) {
//如果没有注解,使用默认的数据源
DynamicDataSource.setDataSource("db1");
} else {
DynamicDataSource.setDataSource(dataSource.name());
}
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
七、将自定义注解启动
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) //重点 禁用springboot默认加载的application.properties单数据源配置 */
@MapperScan(basePackages = "com.xiaobin.mapper")
@Import({DynamicDataSourceConfig.class})
public class StartApp {
public static void main(String[] args) {
SpringApplication.run(StartApp.class);
}
}
八、测试(Mapper编写)
@Repository
public interface UserMapper extends BaseMapper<User> {
@DataSource(name = "db2")
@Select("select * from user")
List<User> list2();
@DataSource(name = "db1")
@Select("select * from user")
List<User> list1();
}
Controller:
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@RequestMapping(value = "/list")
public Object list(HttpServletRequest request){
List<User> list1 = userMapper.list1();
List<User> list2 = userMapper.list2();
Map<String, Object> param = new HashMap<>();
param.put("list1", list1);
param.put("list2", list2);
return param;
}
}