springBoot多数据源的配置
主要看了两个例子
链接1:https://blog.csdn.net/qq_34784893/article/details/80407505
链接2:https://www.cnblogs.com/geekdc/p/10963476.html
根据链接1可以完场双数据源的配置,但是这个方法是需要手动set切换数据源的,不是使用AOP切面
链接2配置完有问题。所有结合一下。
不从数据开始,完全按照执行流程开始
附上yml文件的读取:https://www.cnblogs.com/mysgk/p/9790801.html
调用方式
/**
* 测试查询master 数据源
* @return
*/
@ApiOperation("echo")
@GetMapping("/master")
@DataSourceAop(value = DataSourceType.MASTER) //注解调用不通数据源的枚举
public List<HashMap<String, Object>> master() {
List<HashMap<String, Object>> hashMap = testService.getModel("aaaaaa");
return hashMap;
}
/**
* 测试查询slave 数据源
* @return
*/
@ApiOperation("echo")
@GetMapping("/slave")
@DataSourceAop(value = DataSourceType.SLAVE)
public List<HashMap<String, Object>> slave() {
List<HashMap<String, Object>> hashMap = iTestSlaveService.getSlave("aaaaaa");
return hashMap;
}
使用注解方式切换数据源 返回类型为你的枚举类
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceAop {
//返回类型为你的枚举类
DataSourceType value() default DataSourceType.MASTER;
}
负责管理调用并销毁
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 多数据源处理
* @author DUCHONG
*/
@Aspect
@Order(1)
@Component
public class DataSourceAspect
{
//注意这里的DataSourceAop 为你的自定义注解
@Pointcut("@annotation(com.sasitron.valueadded.config.DataSourceAop)")
public void dsPointCut()
{
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable
{
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSourceAop dataSource = method.getAnnotation(DataSourceAop.class);
if (null!=dataSource)
{
DynamicDataSourceContextHolder.setDateSourceType(dataSource.value().name());
}
try
{
return point.proceed();
}
finally
{
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDateSourceType();
}
}
}
声明一个数据源的枚举类
/**
* 所有数据源的key
* @author Linhai.Tan
*
*/
public enum DataSourceType {
/**
* 默认的数据源
*/
MASTER,
/**
* 新增的数据源
*/
SLAVE;
}
数据源的管理
创建一个安全的线程统一对数据源进行管理,包括(切换、获取、销毁)每个数据源一个线程。
将切换的数据源返回给AbstractRoutingDataSource
/**
* 当前线程需要操作的数据源的标记
* @author Linhai.Tan 2018-4-26
*
*/
public class DynamicDataSourceContextHolder extends AbstractRoutingDataSource {
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
/**
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
*/
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
/**
* 设置数据源的变量
*/
public static void setDateSourceType(String dsType)
{
log.info("切换到{}数据源", dsType);
CONTEXT_HOLDER.set(dsType);
}
/**
* 获得数据源的变量
*/
public static String getDateSourceType()
{
return CONTEXT_HOLDER.get();
}
/**
* 清空数据源变量
*/
public static void clearDateSourceType()
{
CONTEXT_HOLDER.remove();
}
@Override
protected Object determineCurrentLookupKey() {
String key = getDateSourceType();
if (key != null) {
return key;
}
return DataSourceType.MASTER.name();
}
}
数据源的配置
import com.alibaba.druid.pool.DruidDataSource;
import com.sasitron.valueadded.common.DataSourceType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* druid 配置多数据源
*
* @author DUCHONG
*/
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master")
public DataSource mysqlMasterDataSource() {
return new DruidDataSource();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.slave")
public DataSource czSqlServerDataSource() {
return new DruidDataSource();
}
@Primary
@Bean("DataSourceBean")
public DataSource dataSource()
{
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceEnum.MASTER.name(), mysqlMasterDataSource());
targetDataSources.put(DataSourceEnum.SLAVE.name(), czSqlServerDataSource());
DynamicDataSourceContextHolder dataSources=new DynamicDataSourceContextHolder();
dataSources.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
dataSources.setDefaultTargetDataSource(targetDataSources.get(DataSourceEnum.MASTER));// 默认的datasource
return dataSources;
}
}
sqlSessionFactory
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.baomidou.mybatisplus.spring.boot.starter.SpringBootVFS;
import org.apache.ibatis.type.JdbcType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
@Configuration
public class MybatisSqlSession {
@Bean
public MybatisSqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setVfs(SpringBootVFS.class);
sqlSessionFactory.setDataSource(dataSource);
sqlSessionFactory.setTypeAliasesPackage("com.sasitron.valueadded.model.**");
sqlSessionFactory
.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/**/*Mapper.xml"));
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
sqlSessionFactory.setConfiguration(configuration);
return sqlSessionFactory;
}
}
YML文件配置
自己将${ } 修改为自己的配置文件参数
server:
port: ${bbjh.port}
spring:
aop:
proxy-target-class: true
auto: true
datasource:
dynamic:
datasource:
master:
url: ${bbjh.datasource.master.url}
driver-class-name: ${bbjh.datasource.master.driverClassName}
username: ${bbjh.datasource.master.username}
password: ${bbjh.datasource.master.password}
slave:
url: ${bbjh.datasource.slave.url}
driver-class-name: ${bbjh.datasource.slave.driverClassName}
username: ${bbjh.datasource.slave.username}
password: ${bbjh.datasource.slave.password}
POM文件
这里自己根据需求添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--spring-jdbc 数据源-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.25.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatisplus-spring-boot-starter</artifactId>
<version>1.0.5</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!-- sqlServer -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.4.0.jre8</version>
</dependency>