一、yml的数据源配置
配置两个数据源一个叫master主数据源,一个是slave从数据源
默认是主数据源,从数据源需要做切换
datasource:
master:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc-url: jdbc:sqlserver://192.168.110.48:1433;DatabaseName=order_platform_test
username: order_platform_test
password: sncj#$sSSS112
hikari:
connection-test-query: SELECT 1
logging:
level:
com.iot.mapper: debug
slave:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc-url: jdbc:sqlserver://192.168.110.48:1433;database=OrderManagement
username: dev
password: DeV9021##hsn
hikari:
connection-test-query: SELECT 1
logging:
level:
com.iot.mapper: debug
二、多数据源的切面
aspect包下
order(-1)后面解释
package com.dq.workflow.aspect;
import com.dq.workflow.annotation.DynamicSource;
import com.dq.workflow.context.DynamicDataSourceContextHolder;
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.util.Objects;
@Aspect
@Component
@Order(-1)
public class DynamicDataSourceAspect {
@Pointcut("@annotation(com.dq.workflow.annotation.DynamicSource)")
public void dataSourcePointCut(){
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
String dsKey = getDSAnnotation(joinPoint).value();
DynamicDataSourceContextHolder.setContextKey(dsKey);
try{
return joinPoint.proceed();
}finally {
DynamicDataSourceContextHolder.removeContextKey();
}
}
/**
* 根据类或方法获取数据源注解
*/
private DynamicSource getDSAnnotation(ProceedingJoinPoint joinPoint){
Class<?> targetClass = joinPoint.getTarget().getClass();
DynamicSource dsAnnotation = targetClass.getAnnotation(DynamicSource.class);
// 先判断类的注解,再判断方法注解
if(Objects.nonNull(dsAnnotation)){
return dsAnnotation;
}else{
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(DynamicSource.class);
}
}
}
三、动态数据源配置
configuration包下
package com.dq.workflow.configuration;
import com.dq.workflow.constants.DataSourceConstants;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@PropertySource("classpath:application-test.yml")
@MapperScan({"com.dq.workflow.mapper","com.dq.workflow.activiti.mapper"})
public class DynamicDataSourceConfig {
@Bean(DataSourceConstants.DS_KEY_MASTER)
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(DataSourceConstants.DS_KEY_SLAVE)
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public DataSource dynamicDataSource() {
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put(DataSourceConstants.DS_KEY_MASTER, masterDataSource());
dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE, slaveDataSource());
//设置动态数据源
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
return dynamicDataSource;
}
}
四、动态数据源
configuration包下
package com.dq.workflow.configuration;
import com.dq.workflow.context.DynamicDataSourceContextHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 动态数据源
*
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getContextKey();
}
}
五、数据源常量
constants包下
package com.dq.workflow.constants;
/**
* 数据源常量
*
**/
public class DataSourceConstants {
/**
* master数据源
*/
public static final String DS_KEY_MASTER = "master";
/**
* slave数据源
*/
public static final String DS_KEY_SLAVE = "slave";
}
六、上下文处理
context包下
package com.dq.workflow.context;
import com.dq.workflow.constants.DataSourceConstants;
/**
* 动态数据源名称上下文处理
*
**/
public class DynamicDataSourceContextHolder {
/**
* 动态数据源名称上下文
*/
private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>();
/**
* 设置数据源
* @param key
*/
public static void setContextKey(String key){
System.out.println("切换数据源"+key);
DATASOURCE_CONTEXT_KEY_HOLDER.set(key);
}
/**
* 获取数据源名称
* @return
*/
public static String getContextKey(){
String key = DATASOURCE_CONTEXT_KEY_HOLDER.get();
return key == null? DataSourceConstants.DS_KEY_MASTER:key;
}
/**
* 删除当前数据源名称
*/
public static void removeContextKey(){
DATASOURCE_CONTEXT_KEY_HOLDER.remove();
}
}
七、注解配置
annotation包下
package com.dq.workflow.annotation;
import com.dq.workflow.constants.DataSourceConstants;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicSource {
/**
* 数据源名称
*/
String value() default DataSourceConstants.DS_KEY_MASTER;
}
八、主启动类
package com.dq.workflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
org.activiti.spring.boot.SecurityAutoConfiguration.class
},scanBasePackages = {"com.dq.**"})
@EnableSwagger2
@EnableTransactionManagement
public class WorkFlowApplication {
public static void main(String[] args) {
SpringApplication.run(WorkFlowApplication.class, args);
}
}