feat #IAUS2R 重构连接查找逻辑

This commit is contained in:
gaibu
2024-10-13 23:02:39 +08:00
parent 59c3777aa4
commit 8d2e464d3d
6 changed files with 165 additions and 23 deletions

View File

@@ -1,16 +1,20 @@
package com.yomahub.liteflow.parser.sql.datasource;
import cn.hutool.core.collection.CollUtil;
import com.yomahub.liteflow.parser.sql.datasource.impl.BaoMiDouDynamicDsConn;
import com.yomahub.liteflow.parser.sql.datasource.impl.DefaultLiteFlowJdbcConn;
import com.yomahub.liteflow.parser.sql.datasource.impl.LiteFlowAutoLookUpJdbcConn;
import com.yomahub.liteflow.parser.sql.datasource.impl.ShardingJdbcDsConn;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import com.yomahub.liteflow.spi.ContextAware;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 数据源获取接口工厂
@@ -19,22 +23,35 @@ import java.util.Optional;
* @since 2.12.5
*/
public class LiteflowDataSourceConnectFactory {
private static List<LiteFlowDataSourceConnect> CONNECT_LIST = CollUtil.newArrayList(
new BaoMiDouDynamicDsConn(),
new ShardingJdbcDsConn()
);
private static final List<LiteFlowDataSourceConnect> CONNECT_LIST = new CopyOnWriteArrayList<>();
private static final Logger LOG = LoggerFactory.getLogger(LiteflowDataSourceConnectFactory.class);
public static void register() {
ContextAware contextAware = ContextAwareHolder.loadContextAware();
Map<String, LiteFlowDataSourceConnect> beanMap = contextAware.getBeansOfType(LiteFlowDataSourceConnect.class);
Collection<LiteFlowDataSourceConnect> values = beanMap.values();
// 清空原有的列表
CONNECT_LIST.clear();
// 将自定义的放在最前面
CONNECT_LIST.addAll(values);
// 根据类名去重
CONNECT_LIST = CollUtil.distinct(CONNECT_LIST, t -> t.getClass().getName(), true);
// 内置的几种处理器
CONNECT_LIST.add(new DefaultLiteFlowJdbcConn());
CONNECT_LIST.add(new BaoMiDouDynamicDsConn());
CONNECT_LIST.add(new ShardingJdbcDsConn());
// 自动查找放在最后,这个用于兜底处理,这个里面如果找不到,会直接抛出异常
CONNECT_LIST.add(new LiteFlowAutoLookUpJdbcConn());
}
public static Optional<LiteFlowDataSourceConnect> getConnect(SQLParserVO sqlParserVO) {
return CONNECT_LIST.stream().filter(connect -> connect.filter(sqlParserVO)).findFirst();
public static Optional<LiteFlowDataSourceConnect> getConnect(SQLParserVO config) {
for (LiteFlowDataSourceConnect dataSourceConnect : CONNECT_LIST) {
if (dataSourceConnect.filter(config)) {
LOG.debug("use lite-flow-data-source-connect: {}", dataSourceConnect.getClass().getName());
return Optional.of(dataSourceConnect);
}
}
return Optional.empty();
}
}

View File

@@ -0,0 +1,29 @@
package com.yomahub.liteflow.parser.sql.datasource.impl;
import com.yomahub.liteflow.parser.sql.datasource.LiteFlowDataSourceConnect;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* lite flow 默认的数据源连接
*
* @author tkc
* @since 2.12.5
*/
public class DefaultLiteFlowJdbcConn implements LiteFlowDataSourceConnect {
@Override
public boolean filter(SQLParserVO config) {
return config.isUseJdbcConn();
}
@Override
public Connection getConn(SQLParserVO config) throws Exception {
String url = config.getUrl();
String username = config.getUsername();
String password = config.getPassword();
return DriverManager.getConnection(url, username, password);
}
}

View File

@@ -0,0 +1,94 @@
package com.yomahub.liteflow.parser.sql.datasource.impl;
import com.yomahub.liteflow.parser.sql.datasource.LiteFlowDataSourceConnect;
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Optional;
/**
* lite flow 自动查找连接
*
* @author tkc
* @since 2.12.5
*/
public class LiteFlowAutoLookUpJdbcConn implements LiteFlowDataSourceConnect {
private static final Logger LOG = LoggerFactory.getLogger(LiteFlowAutoLookUpJdbcConn.class);
@Override
public boolean filter(SQLParserVO config) {
return true;
}
@Override
public Connection getConn(SQLParserVO config) throws Exception {
return DataSourceBeanNameHolder.autoLookUpConn(config);
}
public static class DataSourceBeanNameHolder {
private static String DATA_SOURCE_NAME = null;
public static synchronized void init(String dataSourceName) {
if (DATA_SOURCE_NAME == null) {
DATA_SOURCE_NAME = dataSourceName;
}
}
public static String getDataSourceName() {
return DATA_SOURCE_NAME;
}
public static boolean isNotInit() {
return DATA_SOURCE_NAME == null;
}
/**
* 自动查找可用数据源
*/
public static Connection autoLookUpConn(SQLParserVO sqlParserVO) throws SQLException {
Connection connection;
Map<String, DataSource> dataSourceMap = ContextAwareHolder.loadContextAware().getBeansOfType(DataSource.class);
if (LiteFlowJdbcUtil.DataSourceBeanNameHolder.isNotInit()) {
synchronized (LiteFlowJdbcUtil.DataSourceBeanNameHolder.class) {
if (LiteFlowJdbcUtil.DataSourceBeanNameHolder.isNotInit()) {
String executeSql = LiteFlowJdbcUtil.buildCheckSql(sqlParserVO);
// 遍历数据源,多数据源场景下,判断哪个数据源有 liteflow 配置
for (Map.Entry<String, DataSource> entry : dataSourceMap.entrySet()) {
String dataSourceName = entry.getKey();
DataSource dataSource = entry.getValue();
if (LiteFlowJdbcUtil.checkConnectionCanExecuteSql(dataSource.getConnection(), executeSql)) {
// 找到数据源名称后,将其缓存起来,下次使用就不再寻找
LiteFlowJdbcUtil.DataSourceBeanNameHolder.init(dataSourceName);
LOG.info("use dataSourceName[{}],has found liteflow config", dataSourceName);
break;
} else {
LOG.info("check dataSourceName[{}],but not has liteflow config", dataSourceName);
}
}
}
}
}
DataSource dataSource = Optional.ofNullable(LiteFlowJdbcUtil.DataSourceBeanNameHolder.getDataSourceName())
.map(dataSourceMap::get)
.orElse(null);
if (dataSource == null) {
throw new ELSQLException("can not found liteflow config in dataSourceName " + dataSourceMap.keySet());
}
connection = dataSource.getConnection();
if (connection == null) {
throw new ELSQLException("can not found liteflow config in dataSourceName " + dataSourceMap.keySet());
}
return connection;
}
}
}

View File

@@ -31,7 +31,7 @@ public class ShardingJdbcDsConn implements LiteFlowDataSourceConnect {
}
boolean classLoadFlag = ClassLoaderUtil.isPresent(Constant.LOAD_CLASS_NAME);
if (!classLoadFlag) {
throw new MissMavenDependencyException(Constant.MAVEN_GROUP_ID, BaoMiDouDynamicDsConn.Constant.MAVEN_ARTIFACT_ID);
throw new MissMavenDependencyException(Constant.MAVEN_GROUP_ID, Constant.MAVEN_ARTIFACT_ID);
}
return true;
}

View File

@@ -30,25 +30,17 @@ public class LiteFlowJdbcUtil {
*/
public static Connection getConn(SQLParserVO sqlParserVO) {
Connection connection = null;
String url = sqlParserVO.getUrl();
String username = sqlParserVO.getUsername();
String password = sqlParserVO.getPassword();
try {
// 如果指定连接查找器,就使用连接查找器获取连接
Optional<LiteFlowDataSourceConnect> connectOpt = LiteflowDataSourceConnectFactory.getConnect(sqlParserVO);
if (connectOpt.isPresent()) {
connection = connectOpt.get().getConn(sqlParserVO);
} else {
// 理论上这里不会走,因为最后一个连接查找器 LiteFlowAutoLookUpJdbcConn 没找到会抛出异常的
// 这里是一个兜底,理论上不会走
throw new ELSQLException("can not found connect by liteflow config");
}
// 如果不配置 jdbc 连接相关配置,代表使用项目数据源
else if (sqlParserVO.isAutoFoundDataSource()) {
connection = DataSourceBeanNameHolder.autoLookUpConn(sqlParserVO);
}
// 如果配置 jdbc 连接相关配置,代表使用指定链接信息
else {
connection = DriverManager.getConnection(url, username, password);
}
} catch (Exception e) {
throw new ELSQLException(e);
}
@@ -118,7 +110,7 @@ public class LiteFlowJdbcUtil {
* @param sqlParserVO sql解析器参数
* @return 返回组合完成的检查sql
*/
private static String buildCheckSql(SQLParserVO sqlParserVO) {
public static String buildCheckSql(SQLParserVO sqlParserVO) {
String chainTableName = sqlParserVO.getChainTableName();
String elDataField = sqlParserVO.getElDataField();
String chainNameField = sqlParserVO.getChainNameField();

View File

@@ -290,6 +290,16 @@ public class SQLParserVO {
StrUtil.isBlank(driverClassName);
}
/**
* 判断是否使用jdbc连接
*/
public boolean isUseJdbcConn(){
return StrUtil.isNotBlank(url) &&
StrUtil.isNotBlank(username) &&
StrUtil.isNotBlank(password) &&
StrUtil.isNotBlank(driverClassName);
}
public Boolean getPollingEnabled() {
return pollingEnabled;
}