所需资源:
1、springBoot
2、mybatis/mybatis-plus
3、Alibab Druid数据库连接池
4、MySql 数据库
项目结构视图:

共分8步完成,步骤如下:
1、依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>
<!--aop切面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.14</version>
</dependency>
2、yml基础配置信息
server:
port: 8088
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
datasource1: #数据源1
url: jdbc:mysql://localhost:3306/datasource1?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
datasource2: #数据源2
url: jdbc:mysql://localhost:3306/datasource2?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
druid: # druid数据库连接池的基本初始化属性
initial-size: 5 # 连接池初始化的大小
min-idle: 1 # 最小空闲的线程数
max-active: 20 # 最大活动的线程数
mybatis-plus:
mapper-locations: classpath:/mapper/*.xml # 配置MyBatis-Plus扫描Mapper文件的位置
type-aliases-package: com.example.sqlite.entity # 创建别名的类所在的包
configuration:
map-underscore-to-camel-case: true # 开启驼峰命名
#sql语句打印
logging:
level:
#路径
com.hua: debug
3、先将两个数据源DataSource 加入IOC容器
package com.hua.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Bean(name = "mysqlDataSource1")
@ConfigurationProperties(prefix = "spring.datasource.datasource1")
public DataSource dataSource1(){
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "mysqlDataSource2")
@ConfigurationProperties(prefix = "spring.datasource.datasource2")
public DataSource dataSource2(){
return DruidDataSourceBuilder.create().build();
}
}
@ConfigurationProperties注解用于将YAML中指定的数据创建成指定的对象,但是,YAML中的数据必须要与对象对象中的属性同名,不然无法由Spring Boot完成赋值。
4、禁掉Spring Boot的数据源自动配置类
package com.hua;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan("com.hua.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.println("Hello word!");
}
}
在启动类上声明需要禁用的自动配置类:exclude = {DataSourceAutoConfiguration.class}
5、 重写DataSource动态分配类
package com.hua.config;
import com.hua.constant.DataSourceType;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Primary
@Component
public class DataSourceManagement extends AbstractRoutingDataSource {
public static ThreadLocal<String> flag = new ThreadLocal<>();
@Resource
private DataSource mysqlDataSource1;
@Resource
private DataSource mysqlDataSource2;
public DataSourceManagement(){
flag.set(DataSourceType.MYSQL_DATASOURCE1.name());
}
@Override
protected Object determineCurrentLookupKey() {
return flag.get();
}
@Override
public void afterPropertiesSet() {
Map<Object,Object> targetDataSource = new ConcurrentHashMap<>();
targetDataSource.put(DataSourceType.MYSQL_DATASOURCE1.name(),mysqlDataSource1);
targetDataSource.put(DataSourceType.MYSQL_DATASOURCE2.name(),mysqlDataSource2);
super.setTargetDataSources(targetDataSource);
super.setDefaultTargetDataSource(mysqlDataSource1);
super.afterPropertiesSet();
}
}
@Primary注解用于帮助我们确定3个DataSource中加载哪个类(IOC中对于DataSource有3个来源,只加载有@Primary注解的)
6、定义枚举类和自定义注解,并开启aop支持
package com.hua.constant;
public enum DataSourceType {
MYSQL_DATASOURCE1,
MYSQL_DATASOURCE2,
}
package com.hua.constant;
import java.lang.annotation.*;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
DataSourceType value() default DataSourceType.MYSQL_DATASOURCE1;
}
package com.hua;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan("com.hua.mapper")
@EnableAspectJAutoProxy //开启Spring Boot对AOP的支持
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.println("Hello word!");
}
}
7、 定义注解的切面类
package com.hua.config;
import com.hua.constant.TargetDataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
@Aspect
@Slf4j
public class TargetDataSourceAspect {
@Before("@within(com.hua.constant.TargetDataSource) || @annotation(com.hua.constant.TargetDataSource)")
public void beforeNoticeUpdateDataSource(JoinPoint joinPoint){
TargetDataSource annotation = null;
Class<? extends Object> target = joinPoint.getTarget().getClass();
if(target.isAnnotationPresent(TargetDataSource.class)){
// 判断类上是否标注着注解
annotation = target.getAnnotation(TargetDataSource.class);
log.info("类上标注了注解");
}else{
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
if(method.isAnnotationPresent(TargetDataSource.class)){
// 判断方法上是否标注着注解,如果类和方法上都没有标注,则报错
annotation = method.getAnnotation(TargetDataSource.class);
log.info("方法上标注了注解");
}else{
throw new RuntimeException("@TargetDataSource注解只能用于类或者方法上, 错误出现在:[" +
target.toString() +" " + method.toString() + "];");
}
}
// 切换数据源
DataSourceManagement.flag.set(annotation.value().name());
}
}
8、 测试
package com.hua.collection;
import com.hua.bean.HotelBean;
import com.hua.bean.HuikeBean;
import com.hua.constant.DataSourceType;
import com.hua.constant.TargetDataSource;
import com.hua.mapper.MyMapper;
import com.hua.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/jk")
public class MyCollection {
@Autowired
private MyService myService;
@Autowired
private MyMapper myMapper;
@TargetDataSource(value = DataSourceType.MYSQL_DATASOURCE1)
@GetMapping("/selectAll")
public Object getAll() {
// 数据处理
List<OneBean> hotelBeans = myService.selectAll();
return hotelBeans;
}
@TargetDataSource(value = DataSourceType.MYSQL_DATASOURCE2)
@GetMapping("/data2")
public Object getAll2() {
// 数据处理
List<TwoBean> huikeBeans = myMapper.selectAll2();
return huikeBeans;
}
}
大佬完整的参考连接:
SpringBoot集成多数据源配置与AOP切换示例
该文详细介绍了如何使用SpringBoot结合mybatis-plus和Druid数据库连接池配置多数据源,并通过AOP实现数据源的动态切换。文中包括了项目依赖设置、YAML配置、数据源容器配置、自动配置类禁用、动态数据源管理、枚举与自定义注解的使用,以及AOP切面类的编写,最后展示了测试用例。
1072





