通过创建数据源扫描类可以创建多数据源,但是每新增一个数据源就要相应的实现,遂想根据包路径自动选择相应的数据源 最终效果:如设置spring.datasource.one.url = xxx,然后mapper类写在one包下如com.mutool.one.mapper.TestMapper即可
设置默认数据源和可选数据源
@Slf4j
@Component
public class DynaCachedDataSource extends AbstractRoutingDataSource implements EnvironmentAware {
private Environment environment;
boolean hasInit = false;
String validationQuerySql = "select 1";// 验证连接是否成功的sql
public DynaCachedDataSource() {
super();
super.setTargetDataSources(new HashMap());
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public Connection getConnection() throws SQLException {
if (!hasInit) {
initDateSourceByProperties();
}
return super.getConnection();
}
/**
* 初始化配置
*/
private void initDateSourceByProperties() {
String driver = environment.getProperty("spring.datasource.driver-class-name");
String url = environment.getProperty("spring.datasource.url");
String username = environment.getProperty("spring.datasource.username");
String password = environment.getProperty("spring.datasource.password");
DruidDataSource defaultDS = new DruidDataSource();
defaultDS.setDriverClassName(driver);
defaultDS.setUrl(url);
defaultDS.setUsername(username);
defaultDS.setPassword(password);
defaultDS.setValidationQuery(validationQuerySql);
//其他属性自行设置
this.setDefaultTargetDataSource(defaultDS);
this.setTargetDataSources(getTargetsMap());
super.afterPropertiesSet();
hasInit = true;
}
private Map<Object, Object> getTargetsMap() {
Map<Object, Object> targets = new HashMap<Object, Object>();
Map<String, Map<String, String>> datasourceGroupMap = getDatasourceConfig();
datasourceGroupMap.forEach((k, v) -> {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(v.get("spring.datasource."+k+".driver-class-name"));
dataSource.setUrl(v.get("spring.datasource."+k+".url"));
dataSource.setUsername(v.get("spring.datasource."+k+".username"));
dataSource.setPassword(v.get("spring.datasource."+k+".password"));
dataSource.setValidationQuery(validationQuerySql);
//其他属性自行设置
targets.put(k, dataSource);
});
return targets;
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
// 线程本地环境
private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();
// 设置数据源
public static void setDataSource(String customerType) {
dataSources.set(customerType);
}
// 获取数据源
public static String getDataSource() {
return dataSources.get();
}
/**
* 从spring配置中获取全部数据源配置
* @return
*/
private Map<String, Map<String, String>> getDatasourceConfig(){
Map<String, Map<String, String>> datasorceGroupMap = new HashMap<>();
StandardServletEnvironment standardServletEnvironment = (StandardServletEnvironment) environment;
Iterator<PropertySource<?>> iterator = standardServletEnvironment.getPropertySources().iterator();
while (iterator.hasNext()) {
PropertySource<?> source = iterator.next();
Object o = source.getSource();
if (o instanceof Map) {
for (Map.Entry<String, Object> entry : ((Map<String, Object>) o).entrySet()) {
String key = entry.getKey();
//判断如果以spring.datasource开始的配置取出
if(!key.startsWith("spring.datasource")){
continue;
}
String value = standardServletEnvironment.getProperty(key);
String datasourceGroup = ReUtil.getGroup1("datasource\\.(.*?)\\.", value);
if(StrUtil.isBlank(datasourceGroup)){
datasourceGroup = "default";
}
Map<String, String> datasourceConfigMap = datasorceGroupMap.get(datasourceGroup);
if(datasourceConfigMap == null){
datasourceConfigMap = new HashMap<>();
datasorceGroupMap.put(datasourceGroup, datasourceConfigMap);
}
datasourceConfigMap.put(key, value);
}
}
}
return datasorceGroupMap;
}
}
动态选择数据源
@Slf4j
@Component
@Aspect
public class DynaDataSourceInterceptor {
@Before("execution(* com.mutool..mapper.*Mapper.*(..))")
public void dynamicSetDataSoruce(JoinPoint joinPoint) throws Exception {
Object target = joinPoint.getTarget();
Class<?> clazz = target.getClass();
String className = clazz.getName();
if(Proxy.isProxyClass(target.getClass())) {
Type[] types = AopUtils.getTargetClass(target).getGenericInterfaces();
className = types[0].getTypeName();
}
if(!className.contains(".mapper.")){
log.error("数据源切面拦截解析包路径错误,解析得到类名:{}", className);
return;
}
String pkg = className.substring(0, className.indexOf(".mapper."));
pkg = pkg.substring(pkg.lastIndexOf('.') + 1);
if (pkg.equals("mybatis")) {
Thread.sleep(1000);
}
DynaCachedDataSource.setDataSource(pkg);
}
}