使用springboot项目时用到了多数据源配置,在网上看了很多总感觉达不到自己的要求,所以浏览完之后决定自己写一个。
废话不说,上代码
pom.xml需要用到的支持
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.5.RELEASE
com.example.boot
proliu
0.0.1-SNAPSHOT
proliu
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-data-rest
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework
spring-jdbc
5.1.0.RELEASE
com.alibaba
druid-spring-boot-starter
1.1.9
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
org.mybatis
mybatis
3.4.6
org.springframework.boot
spring-boot-maven-plugin
src/main/java
**/*.xml
src/main/resources
我比较懒就把所有的全都粘过来了,但是这是一个我用来测试多数据源的项目,多余的支持包不多。
再来看application.yml
#使用多数据源配置,自定义配置我订的规则,就是在项目中让程序读取到的配置的key值
spring:
#list 数据源名字的集合 名字自己订只需要在每个数据源上一级以该名字定义 第一个为默认数据源
list: master,save
datasource:
#数据源配置基本配置 其他的统一配置可以自己加 我比较懒 注:该级别的名字应该与上边list一一对应,不然会怎么样我也不知道 嘿嘿
master:
driverClassCame: com.mysql.jdbc.Driver
url: ://*************:3306/*************?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
username: root
password:
save:
driverClassCame: com.mysql.jdbc.Driver
url: jdbc:mysql://*************:3306/*************?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
username: root
password:
#使用mybatis 需要的两个配置信息
mybatis:
mapper-locations: classpath*:com/example/boot/proliu/map/*.xml
type-aliases-package: com.example.boot.proliu.entity
使用自定义多数据源配置 首先就是再启动类去掉项目自带的自动加载数据源代码
//exclude = DataSourceAutoConfiguration.class 去掉自动加载数据源 不然会造成循环依赖
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@MapperScan(basePackages = "com.example.boot.proliu.map")//mapper扫描
public class ProliuApplication {
public static void main(String[] args) {
SpringApplication.run(ProliuApplication.class, args);
}
}
使用多数据源需要自己定义配置文件信息获取和数据源配置 进入主题
package com.example.boot.proliu.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
/**
* 继承AbstractRoutingDataSource重写determineCurrentLookupKey
* 自己定义需要那个数据源
*/
public class MyDynamicDataSource extends AbstractRoutingDataSource {
//线程独有数据源切换 使用 ThreadLocal
private final static ThreadLocal databasekey = new ThreadLocal<>();
/**
* 配置DataSource, defaultTargetDataSource为主数据库 TargetDataSources为数据源集合
*/
public MyDynamicDataSource(DataSource defaultTargetDataSource, Map
简单解释一下 AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上。
有了数据源切换类了,下边贴一下数据源加载类
package com.example.boot.proliu.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
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.core.env.Environment;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class MyDataSourse {
@Autowired
Environment env;
/**
* 将获取的数据源配置注册到MyDynamicDataSource 或者说 AbstractRoutingDataSource 中
* @return
*/
@Bean
@Primary
public MyDynamicDataSource dataSource() {
Map
到这基本的数据源配置就完成了。只需要在需切换的数据源的地方
MyDynamicDataSource.setDatabasekey(key); //参数为配置中list中的数据源名称
注意 使用这种方式调用完后应该释放数据源回复到默认状态
MyDynamicDataSource.removeDatabasekey();
但是这么搞对代码侵入性太强 因此使用aop形式对服务方法进行增强,在增强中进行数据源切换
首先 定义注解 上代码
package com.example.boot.proliu.aspect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicDateSource {
String value() default "";
}
这里不多解释,不懂的可以看看java注解这一块
接下来 就是增强类 代码
package com.example.boot.proliu.aspect;
import com.example.boot.proliu.config.MyDynamicDataSource;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 里边用到的几个注解
*
* @Aspect
* @Pointcut
* @Before
* @After 这都是aop这一块的注解
*/
@Aspect
@Component
public class DataSpurceAspect {
//定义切面
@Pointcut("@annotation(com.example.boot.proliu.aspect.DynamicDateSource)")
public void annotationPointCut() {
}
//前置增强 检查方法是否需要切换数据源 和数据源切换
@Before("annotationPointCut()")
public void before(JoinPoint joinPoint){
MethodSignature sign = (MethodSignature)joinPoint.getSignature();
Method method = sign.getMethod();
DynamicDateSource annotation = method.getAnnotation(DynamicDateSource.class);
if(annotation != null){
MyDynamicDataSource.setDatabasekey(annotation.value());
}
}
//后置增强 方法调用完之后回复默认数据源 @After注解是不管怎样都会执行
@After("annotationPointCut()")
public void after(){
if(null != MyDynamicDataSource.getDatabasekey())
MyDynamicDataSource.removeDatabasekey();
}
}
到配置基本完成
只需要在需要的切换的方法上加上
@DynamicDateSource(“数据源的KEY”)注解就可以了
附上项目地址
springboot 动态数据源配置
项目地址 https://github.com/ljhaa/dynamicDataSource.git