springBoot学习笔记(2.5)—— 整合mybatis配置多数据源
一、配置步骤
1.引入jar包
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>springboot-datasource</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-datasource</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version></dependency><!--分数据源--><!-- 阿里连接池--><!--分数据源--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10 </version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
2.配置项目文件
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverdruid:#数据源1first:# 数据源基本配置url: jdbc:mysql://101.34.49.127:3306/springBootAll?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=falseusername: rootpassword: 123456# 数据源2second:url: jdbc:mysql://localhost:3306/springBootAll?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=falseusername: rootpassword: 123456mybatis:mapper-locations: classpath:mybatis/mapper/*.xmlserver:port: 8082 # 配置项目启动端口
3.数据源切换配置
3.1 项目文件截图

3.2 CurDataSouce类切换数据源的注释
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface CurDataSource {String name() default "";}
3.3 DataSourceAspect类多数据源切面处理
@Slf4j@Aspect@Componentpublic class DataSourceAspect implements Ordered {@Pointcut("@annotation(com.example.springbootdatasource.datasource.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);if (ds == null) {DynamicDataSource.setDataSource(DataSourceNames.FIRST);log.debug("set datasource is " + DataSourceNames.FIRST);} else {DynamicDataSource.setDataSource(ds.name());log.debug("set datasource is " + ds.name());}try {return point.proceed();} finally {DynamicDataSource.clearDataSource();log.debug("clean datasource");}}@Overridepublic int getOrder() {return 1;}}
3.4 DataSourceNames类枚举数据源
public interface DataSourceNames {String FIRST = "first";String SECOND = "second";}
3.5 DynamicDataSource类
/*** 扩展 Spring 的 AbstractRoutingDataSource 抽象类,重写 determineCurrentLookupKey 方法* 动态数据源* determineCurrentLookupKey() 方法决定使用哪个数据源** @author xiaohe* @version V1.0.0*/public class DynamicDataSource extends AbstractRoutingDataSource {/*** ThreadLocal 用于提供线程局部变量,在多线程环境可以保证各个线程里的变量独立于其它线程里的变量。* 也就是说 ThreadLocal 可以为每个线程创建一个【单独的变量副本】,相当于线程的 private static 类型变量。*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();/*** 决定使用哪个数据源之前需要把多个数据源的信息以及默认数据源信息配置好** @param defaultTargetDataSource 默认数据源* @param targetDataSources 目标数据源*/public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected Object determineCurrentLookupKey() {return getDataSource();}public static void setDataSource(String dataSource) {CONTEXT_HOLDER.set(dataSource);}public static String getDataSource() {return CONTEXT_HOLDER.get();}public static void clearDataSource() {CONTEXT_HOLDER.remove();}}
3.6 DynamicDataSourceConfig类
/*** 配置多数据源* @author xiaohe* @version V1.0.0*/@Configurationpublic class DynamicDataSourceConfig {@Bean@ConfigurationProperties("spring.datasource.druid.first")public DataSource firstDataSource(){return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties("spring.datasource.druid.second")public DataSource secondDataSource(){return DruidDataSourceBuilder.create().build();}@Bean@Primarypublic DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {Map<Object, Object> targetDataSources = new HashMap<>(5);targetDataSources.put(DataSourceNames.FIRST, firstDataSource);targetDataSources.put(DataSourceNames.SECOND, secondDataSource);return new DynamicDataSource(firstDataSource, targetDataSources);}}
4.springboot主方法
//启动时不引入数据库配置@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})@MapperScan(basePackages = "com.example.springbootdatasource")@EnableScheduling@EnableAspectJAutoProxy(exposeProxy = true)@Import({DynamicDataSourceConfig.class})public class SpringbootDatasourceApplication {public static void main(String[] args) {SpringApplication.run(SpringbootDatasourceApplication.class, args);}}
5.controller层接口
@Controller@RequestMapping("userController")public class UserController {@ResourceUserService userService;/***** description: findUser* version: 1.0 ->* date: 2022/1/28 15:11* author: xiaYZ* iteration: 迭代说明* @param id* @return java.lang.String*/@ResponseBody@GetMapping("findUserFromFirst")@Description("申明使用数据源一进行操作")public String findUserFromFirst(Integer id){User user = new User();try{user = userService.selectDataFromFirst(id);}catch (Exception e){e.printStackTrace();}return user.toString();}/**** description: findUserSecond* version: 1.0 ->* date: 2022/2/1 18:14* author: xiaYZ* iteration: 迭代说明* @param id* @return java.lang.String*/@ResponseBody@GetMapping("findUserFromSecond")@Description("查询用户数据从数据源二")public String findUserFromSecond(Integer id){User user = new User();try{user = userService.selectDataSecond(id);}catch (Exception e){e.printStackTrace();}return user.toString();}}
6.service层方法
@Servicepublic class UserService{@Resourceprivate UserMapper userMapper;/*** description: 申明使用数据源一进行操作* version: 1.0* date: 2022/2/1 18:10* author: xiaYZ* iteration: 迭代说明* @param id* @return*/@CurDataSource(name = DataSourceNames.FIRST)public User selectDataFromFirst(Integer id) {return userMapper.selectByPrimaryKey(id);}/*** description: 申明使用数据源二进行操作* version: 1.0* date: 2022/2/1 19:27* author: xiaYZ* iteration: 迭代说明* @param id* @return*/@CurDataSource(name = DataSourceNames.SECOND)public User selectDataSecond(Integer id){return userMapper.selectByPrimaryKey(id);}}
使用@CurDataSource注解声明使用那个数据源
二、项目运行截图
1. 数据库截图
1.1本地数据截图

1.2 服务器上数据库截图

2.接口调用截图
2.1 服务器数据源接口截图

2.2 本地接口数据源截图

总结
- 引入对应jar包
- 构建数据源切换配置
- service层使用@CurDataSource注解切换配置,如果没有使用此注解默认使用上一个接口的数据源
