一、自定义DB注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DS {
String value();
}
二、配置properties数据源
文件名:jdbc.properties
# slave-authserver
spring.datasource.slave.authserver.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.authserver.jdbc-url=jdbc:mysql://localhost:3306/smart-authserver?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.authserver.username=root
spring.datasource.slave.authserver.password=123456
# slave-data
spring.datasource.slave.data.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.data.jdbc-url=jdbc:mysql://localhost:3306/smart-data?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.data.username=root
spring.datasource.slave.data.password=123456
# slave-kpi
spring.datasource.slave.kpi.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.kpi.jdbc-url=jdbc:mysql://localhost:3306/smart-kpi?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.kpi.username=root
spring.datasource.slave.kpi.password=123456
# slave-logistics
spring.datasource.slave.logistics.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.logistics.jdbc-url=jdbc:mysql://localhost:3306/smart-logistics?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.logistics.username=root
spring.datasource.slave.logistics.password=123456
三、设置各数据源常量
public interface DataSourceConstants {
String DS_KEY_SLAVE_DATA = "DS_KEY_SLAVE_DATA";
String DS_KEY_SLAVE_AUTH = "DS_KEY_SLAVE_AUTH";
String DS_KEY_SLAVE_LOGISTICS = "DS_KEY_SLAVE_LOGISTICS";
String DS_KEY_SLAVE_KPI = "DS_KEY_SLAVE_KPI";
}
四、Spring配置多数据源
import com.jnx.smart.authserver.db.DynamicDataSource;
import com.jnx.smart.base.constant.DataSourceConstants;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
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:jdbc.properties")
@MapperScan(basePackages = {
"com.jnx.smart.authserver.business.repository.dao",
"com.jnx.smart.data.business.repository.dao",
"com.jnx.smart.assess.business.repository.dao",
"com.jnx.smart.logistics.business.repository.dao"})
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class DynamicDataSourceConfig {
@Bean
@Primary
public DataSource dynamicDataSource() {
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_AUTH, slaveDataSourceAuth());
dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_DATA, slaveDataSourceData());
dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_KPI, slaveDataSourceKpi());
dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_LOGISTICS, slaveDataSourceLogistics());
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(slaveDataSourceAuth());
return dynamicDataSource;
}
@Bean("DS_KEY_SLAVE_AUTH")
@ConfigurationProperties(prefix = "spring.datasource.slave.authserver")
public DataSource slaveDataSourceAuth() {
return DataSourceBuilder.create().build();
}
@Bean("DS_KEY_SLAVE_DATA")
@ConfigurationProperties(prefix = "spring.datasource.slave.data")
public DataSource slaveDataSourceData() {
return DataSourceBuilder.create().build();
}
@Bean("DS_KEY_SLAVE_KPI")
@ConfigurationProperties(prefix = "spring.datasource.slave.kpi")
public DataSource slaveDataSourceKpi() {
return DataSourceBuilder.create().build();
}
@Bean("DS_KEY_SLAVE_LOGISTICS")
@ConfigurationProperties(prefix = "spring.datasource.slave.logistics")
public DataSource slaveDataSourceLogistics() {
return DataSourceBuilder.create().build();
}
}
五、数据源的上下文配置
数据源上下文设置
import com.jnx.smart.base.constant.DataSourceConstants;
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>();
public static void setContextKey(String key) {
DATASOURCE_CONTEXT_KEY_HOLDER.set(key);
}
public static String getContextKey() {
String key = DATASOURCE_CONTEXT_KEY_HOLDER.get();
return key == null ? DataSourceConstants.DS_KEY_SLAVE_AUTH : key;
}
public static void removeContextKey() {
DATASOURCE_CONTEXT_KEY_HOLDER.remove();
}
}
获取上下文的数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getContextKey();
}
}
AOP切面处理
import com.jnx.smart.base.annotation.DS;
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.stereotype.Component;
import java.util.Objects;
@Aspect
@Component
public class DynamicDataSourceAspect {
@Pointcut("@annotation(com.jnx.smart.base.annotation.DS)")
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 DS getDSAnnotation(ProceedingJoinPoint joinPoint) {
Class<?> targetClass = joinPoint.getTarget().getClass();
DS dsAnnotation = targetClass.getAnnotation(DS.class);
if (Objects.nonNull(dsAnnotation)) {
return dsAnnotation;
} else {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(DS.class);
}
}
}
六、使用
在完成以上配置后,直接在需要使用的service方法上,打上注解任选一个需要的数据源@DB(value=DataSourceConstants.DS_KEY_SLAVE_DATA) ,程序执行时就会从指定的数据源进行操作。
|