mirror of https://gitee.com/dromara/liteFlow
feat #IAUS2R sql插件支持指定数据源
This commit is contained in:
parent
2ea9e187ff
commit
59c3777aa4
|
@ -0,0 +1,39 @@
|
|||
package com.yomahub.liteflow.exception;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 缺少 maven 依赖异常
|
||||
*
|
||||
* @author tkc
|
||||
* @since 2.12.5
|
||||
*/
|
||||
public class MissMavenDependencyException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TEMPLATE = "miss maven dependency " + "\n" +
|
||||
"<dependency>\n" +
|
||||
" <groupId>{groupId}</groupId>\n" +
|
||||
" <artifactId>{artifactId}</artifactId>\n" +
|
||||
" <version>${version}</version>\n" +
|
||||
"</dependency>";
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
public MissMavenDependencyException(String groupId, String artifactId) {
|
||||
this.message = StrUtil.format(TEMPLATE, groupId, artifactId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,8 +33,20 @@ public interface ContextAware extends SpiPriority {
|
|||
*/
|
||||
<T> Map<String, T> getBeansOfType(Class<T> type);
|
||||
|
||||
/**
|
||||
* 判断是否存在指定名称的bean
|
||||
*
|
||||
* @param beanName bean 名称
|
||||
*/
|
||||
boolean hasBean(String beanName);
|
||||
|
||||
/**
|
||||
* 判断是否存在指定类型的bean
|
||||
*
|
||||
* @param clazz 类型
|
||||
*/
|
||||
boolean hasBean(Class<?> clazz);
|
||||
|
||||
Object registerDeclWrapBean(String beanName, DeclWarpBean declWarpBean);
|
||||
|
||||
}
|
||||
|
|
|
@ -54,6 +54,11 @@ public class LocalContextAware implements ContextAware {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBean(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object registerDeclWrapBean(String beanName, DeclWarpBean declWarpBean) {
|
||||
return null;
|
||||
|
|
|
@ -25,5 +25,23 @@
|
|||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 苞米豆动态数据源 -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring</artifactId>
|
||||
<version>${dynamic-datasource.version}</version>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Sharding JDBC -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shardingsphere</groupId>
|
||||
<artifactId>sharding-jdbc-core</artifactId>
|
||||
<version>${sharding-jdbc.version}</version>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil;
|
|||
import com.yomahub.liteflow.core.FlowInitHook;
|
||||
import com.yomahub.liteflow.parser.constant.ReadType;
|
||||
import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser;
|
||||
import com.yomahub.liteflow.parser.sql.datasource.LiteflowDataSourceConnectFactory;
|
||||
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
|
||||
import com.yomahub.liteflow.parser.sql.read.SqlReadFactory;
|
||||
import com.yomahub.liteflow.parser.sql.util.JDBCHelper;
|
||||
|
@ -58,6 +59,9 @@ public class SQLXmlELParser extends ClassXmlFlowELParser {
|
|||
// 初始化 SqlReadFactory
|
||||
SqlReadFactory.registerRead(sqlParserVO);
|
||||
|
||||
// 初始化连接器
|
||||
LiteflowDataSourceConnectFactory.register();
|
||||
|
||||
// 注册轮询任务
|
||||
SqlReadFactory.registerSqlReadPollTask(ReadType.CHAIN);
|
||||
SqlReadFactory.registerSqlReadPollTask(ReadType.SCRIPT);
|
||||
|
@ -92,7 +96,7 @@ public class SQLXmlELParser extends ClassXmlFlowELParser {
|
|||
* @param sqlParserVO sqlParserVO
|
||||
*/
|
||||
private void checkParserVO(SQLParserVO sqlParserVO) {
|
||||
if (sqlParserVO.isDefaultDataSource()) {
|
||||
if (sqlParserVO.isAutoFoundDataSource()) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isEmpty(sqlParserVO.getUrl())) {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.yomahub.liteflow.parser.sql.datasource;
|
||||
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* 数据源获取接口
|
||||
*
|
||||
* @author tkc
|
||||
* @since 2.12.5
|
||||
*/
|
||||
public interface LiteFlowDataSourceConnect {
|
||||
|
||||
/**
|
||||
* 检查是否支持该数据源
|
||||
*/
|
||||
boolean filter(SQLParserVO config);
|
||||
|
||||
/**
|
||||
* 获取连接
|
||||
*/
|
||||
Connection getConn(SQLParserVO config) throws Exception;
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
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.ShardingJdbcDsConn;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
import com.yomahub.liteflow.spi.ContextAware;
|
||||
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 数据源获取接口工厂
|
||||
*
|
||||
* @author tkc
|
||||
* @since 2.12.5
|
||||
*/
|
||||
public class LiteflowDataSourceConnectFactory {
|
||||
private static List<LiteFlowDataSourceConnect> CONNECT_LIST = CollUtil.newArrayList(
|
||||
new BaoMiDouDynamicDsConn(),
|
||||
new ShardingJdbcDsConn()
|
||||
);
|
||||
|
||||
public static void register() {
|
||||
ContextAware contextAware = ContextAwareHolder.loadContextAware();
|
||||
Map<String, LiteFlowDataSourceConnect> beanMap = contextAware.getBeansOfType(LiteFlowDataSourceConnect.class);
|
||||
Collection<LiteFlowDataSourceConnect> values = beanMap.values();
|
||||
CONNECT_LIST.addAll(values);
|
||||
|
||||
// 根据类名去重
|
||||
CONNECT_LIST = CollUtil.distinct(CONNECT_LIST, t -> t.getClass().getName(), true);
|
||||
}
|
||||
|
||||
public static Optional<LiteFlowDataSourceConnect> getConnect(SQLParserVO sqlParserVO) {
|
||||
return CONNECT_LIST.stream().filter(connect -> connect.filter(sqlParserVO)).findFirst();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.yomahub.liteflow.parser.sql.datasource.impl;
|
||||
|
||||
import cn.hutool.core.util.ClassLoaderUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.yomahub.liteflow.exception.MissMavenDependencyException;
|
||||
import com.yomahub.liteflow.parser.sql.datasource.LiteFlowDataSourceConnect;
|
||||
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
import com.yomahub.liteflow.spi.ContextAware;
|
||||
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 苞米豆动态数据源
|
||||
*
|
||||
* @author tkc
|
||||
* @since 2.12.5
|
||||
*/
|
||||
public class BaoMiDouDynamicDsConn implements LiteFlowDataSourceConnect {
|
||||
@Override
|
||||
public boolean filter(SQLParserVO config) {
|
||||
// 是否配置苞米豆动态数据源配置
|
||||
boolean configFlag = Optional.ofNullable(config.getBaomidou())
|
||||
.map(SQLParserVO.DataSourceConfig::getDataSourceName)
|
||||
.isPresent();
|
||||
if (!configFlag) {
|
||||
return false;
|
||||
}
|
||||
boolean classLoadFlag = ClassLoaderUtil.isPresent(Constant.LOAD_CLASS_NAME);
|
||||
if (!classLoadFlag) {
|
||||
throw new MissMavenDependencyException(Constant.MAVEN_GROUP_ID, Constant.MAVEN_ARTIFACT_ID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConn(SQLParserVO config) throws Exception {
|
||||
String dataSourceName = config.getBaomidou().getDataSourceName();
|
||||
ContextAware contextAware = ContextAwareHolder.loadContextAware();
|
||||
DynamicRoutingDataSource dynamicRoutingDataSource = contextAware.getBean(DynamicRoutingDataSource.class);
|
||||
Map<String, DataSource> dataSources = dynamicRoutingDataSource.getDataSources();
|
||||
if (!dataSources.containsKey(dataSourceName)) {
|
||||
throw new ELSQLException(StrUtil.format("can not found {} datasource", dataSourceName));
|
||||
}
|
||||
|
||||
DataSource dataSource = dynamicRoutingDataSource.getDataSource(dataSourceName);
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* 常量类
|
||||
*/
|
||||
public static class Constant {
|
||||
public static final String LOAD_CLASS_NAME = "com.baomidou.dynamic.datasource.DynamicRoutingDataSource";
|
||||
public static final String MAVEN_GROUP_ID = "com.baomidou";
|
||||
public static final String MAVEN_ARTIFACT_ID = "dynamic-datasource-spring-boot-starter";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.yomahub.liteflow.parser.sql.datasource.impl;
|
||||
|
||||
import cn.hutool.core.util.ClassLoaderUtil;
|
||||
import com.yomahub.liteflow.exception.MissMavenDependencyException;
|
||||
import com.yomahub.liteflow.parser.sql.datasource.LiteFlowDataSourceConnect;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
import com.yomahub.liteflow.spi.ContextAware;
|
||||
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* ShardingJdbc 动态数据源
|
||||
*
|
||||
* @author tkc
|
||||
* @since 2.12.5
|
||||
*/
|
||||
public class ShardingJdbcDsConn implements LiteFlowDataSourceConnect {
|
||||
|
||||
@Override
|
||||
public boolean filter(SQLParserVO config) {
|
||||
// 是否配置 sharding jdbc 动态数据源配置
|
||||
boolean configFlag = Optional.ofNullable(config.getShardingjdbc())
|
||||
.map(SQLParserVO.DataSourceConfig::getDataSourceName)
|
||||
.isPresent();
|
||||
|
||||
if (!configFlag) {
|
||||
return false;
|
||||
}
|
||||
boolean classLoadFlag = ClassLoaderUtil.isPresent(Constant.LOAD_CLASS_NAME);
|
||||
if (!classLoadFlag) {
|
||||
throw new MissMavenDependencyException(Constant.MAVEN_GROUP_ID, BaoMiDouDynamicDsConn.Constant.MAVEN_ARTIFACT_ID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConn(SQLParserVO config) throws Exception {
|
||||
ContextAware contextAware = ContextAwareHolder.loadContextAware();
|
||||
|
||||
return contextAware.getBean(DataSource.class).getConnection();
|
||||
}
|
||||
|
||||
|
||||
public static class Constant {
|
||||
public static final String LOAD_CLASS_NAME = "org.apache.shardingsphere.driver.jdbc.core.datasource.ShardingSphereDataSource";
|
||||
public static final String MAVEN_GROUP_ID = "org.apache.shardingsphere";
|
||||
public static final String MAVEN_ARTIFACT_ID = "sharding-jdbc-core";
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package com.yomahub.liteflow.parser.sql.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.parser.sql.datasource.LiteFlowDataSourceConnect;
|
||||
import com.yomahub.liteflow.parser.sql.datasource.LiteflowDataSourceConnectFactory;
|
||||
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
|
||||
|
@ -10,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
|||
import javax.sql.DataSource;
|
||||
import java.sql.*;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class LiteFlowJdbcUtil {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LiteFlowJdbcUtil.class);
|
||||
|
@ -17,7 +20,10 @@ public class LiteFlowJdbcUtil {
|
|||
|
||||
/**
|
||||
* 获取链接
|
||||
* 此方法会根据配置,判读使用指定数据源,还是IOC容器中已有的数据源
|
||||
* 此方法会从多个角度查找数据源,优先级从上到下
|
||||
* 1. 自定义连接器获取,实现了 DataBaseConnect 接口
|
||||
* 2. 没有配置数据源连接配置,判断标准参考 SqlParserVO#isDefaultDataSource(),自动寻找IOC容器中已有的数据源
|
||||
* 3. 使用数据源配置,使用 jdbc 创建连接
|
||||
*
|
||||
* @param sqlParserVO sql解析器参数
|
||||
* @return 返回数据库连接
|
||||
|
@ -29,26 +35,14 @@ public class LiteFlowJdbcUtil {
|
|||
String password = sqlParserVO.getPassword();
|
||||
|
||||
try {
|
||||
// 如果指定连接查找器,就使用连接查找器获取连接
|
||||
Optional<LiteFlowDataSourceConnect> connectOpt = LiteflowDataSourceConnectFactory.getConnect(sqlParserVO);
|
||||
if (connectOpt.isPresent()) {
|
||||
connection = connectOpt.get().getConn(sqlParserVO);
|
||||
}
|
||||
// 如果不配置 jdbc 连接相关配置,代表使用项目数据源
|
||||
if (sqlParserVO.isDefaultDataSource()) {
|
||||
String executeSql = buildCheckSql(sqlParserVO);
|
||||
Map<String, DataSource> dataSourceMap = ContextAwareHolder.loadContextAware().getBeansOfType(DataSource.class);
|
||||
// 遍历数据源,多数据源场景下,判断哪个数据源有 liteflow 配置
|
||||
for (Map.Entry<String, DataSource> entry : dataSourceMap.entrySet()) {
|
||||
String dataSourceName = entry.getKey();
|
||||
DataSource dataSource = entry.getValue();
|
||||
|
||||
if (checkConnectionCanExecuteSql(dataSource.getConnection(), executeSql)) {
|
||||
connection = dataSource.getConnection();
|
||||
LOG.info("use dataSourceName[{}],has found liteflow config", dataSourceName);
|
||||
break;
|
||||
} else {
|
||||
LOG.info("check dataSourceName[{}],but not has liteflow config", dataSourceName);
|
||||
}
|
||||
}
|
||||
if (connection == null) {
|
||||
throw new ELSQLException("can not found liteflow config in dataSourceName " + dataSourceMap.keySet());
|
||||
}
|
||||
else if (sqlParserVO.isAutoFoundDataSource()) {
|
||||
connection = DataSourceBeanNameHolder.autoLookUpConn(sqlParserVO);
|
||||
}
|
||||
// 如果配置 jdbc 连接相关配置,代表使用指定链接信息
|
||||
else {
|
||||
|
@ -62,6 +56,7 @@ public class LiteFlowJdbcUtil {
|
|||
return connection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断连接是否可以执行指定 sql
|
||||
*
|
||||
|
@ -129,4 +124,63 @@ public class LiteFlowJdbcUtil {
|
|||
String chainNameField = sqlParserVO.getChainNameField();
|
||||
return StrUtil.format(CHECK_SQL_PATTERN, chainNameField, elDataField, chainTableName);
|
||||
}
|
||||
|
||||
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 (DataSourceBeanNameHolder.isNotInit()) {
|
||||
synchronized (DataSourceBeanNameHolder.class) {
|
||||
if (DataSourceBeanNameHolder.isNotInit()) {
|
||||
String executeSql = buildCheckSql(sqlParserVO);
|
||||
// 遍历数据源,多数据源场景下,判断哪个数据源有 liteflow 配置
|
||||
for (Map.Entry<String, DataSource> entry : dataSourceMap.entrySet()) {
|
||||
String dataSourceName = entry.getKey();
|
||||
DataSource dataSource = entry.getValue();
|
||||
|
||||
if (checkConnectionCanExecuteSql(dataSource.getConnection(), executeSql)) {
|
||||
// 找到数据源名称后,将其缓存起来,下次使用就不再寻找
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,6 +142,16 @@ public class SQLParserVO {
|
|||
*/
|
||||
private Boolean sqlLogEnabled = true;
|
||||
|
||||
/**
|
||||
* 苞米豆动态数据源配置
|
||||
*/
|
||||
private DataSourceConfig baomidou;
|
||||
|
||||
/**
|
||||
* sharding jdbc 动态数据源配置
|
||||
*/
|
||||
private DataSourceConfig shardingjdbc;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
@ -271,10 +281,13 @@ public class SQLParserVO {
|
|||
}
|
||||
|
||||
/**
|
||||
* 判断配资是否使用 IOC 已有数据源
|
||||
* 判断是否自动查找数据源
|
||||
*/
|
||||
public boolean isDefaultDataSource() {
|
||||
return StrUtil.isBlank(url) && StrUtil.isBlank(username) && StrUtil.isBlank(password) && StrUtil.isBlank(driverClassName);
|
||||
public boolean isAutoFoundDataSource() {
|
||||
return StrUtil.isBlank(url) &&
|
||||
StrUtil.isBlank(username) &&
|
||||
StrUtil.isBlank(password) &&
|
||||
StrUtil.isBlank(driverClassName);
|
||||
}
|
||||
|
||||
public Boolean getPollingEnabled() {
|
||||
|
@ -363,4 +376,32 @@ public class SQLParserVO {
|
|||
public void setScriptCustomSql(String scriptCustomSql) {
|
||||
this.scriptCustomSql = scriptCustomSql;
|
||||
}
|
||||
|
||||
public DataSourceConfig getBaomidou() {
|
||||
return baomidou;
|
||||
}
|
||||
|
||||
public void setBaomidou(DataSourceConfig baomidou) {
|
||||
this.baomidou = baomidou;
|
||||
}
|
||||
|
||||
public DataSourceConfig getShardingjdbc() {
|
||||
return shardingjdbc;
|
||||
}
|
||||
|
||||
public void setShardingjdbc(DataSourceConfig shardingjdbc) {
|
||||
this.shardingjdbc = shardingjdbc;
|
||||
}
|
||||
|
||||
public static class DataSourceConfig {
|
||||
private String dataSourceName;
|
||||
|
||||
public String getDataSourceName() {
|
||||
return dataSourceName;
|
||||
}
|
||||
|
||||
public void setDataSourceName(String dataSourceName) {
|
||||
this.dataSourceName = dataSourceName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,11 @@ public class SolonContextAware implements ContextAware {
|
|||
return Solon.context().hasWrap(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBean(Class<?> clazz) {
|
||||
return CollUtil.size(getBeansOfType(clazz)) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return 1;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.yomahub.liteflow.spi.spring;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.yomahub.liteflow.core.proxy.DeclWarpBean;
|
||||
import com.yomahub.liteflow.spi.ContextAware;
|
||||
|
@ -122,6 +123,11 @@ public class SpringAware implements ApplicationContextAware, ContextAware {
|
|||
return applicationContext.containsBean(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBean(Class<?> clazz) {
|
||||
return CollUtil.size(getBeansOfType(clazz)) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return 1;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.yomahub.liteflow.test.sql;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/application-baomidou-data-source-xml.properties")
|
||||
@SpringBootTest(classes = SQLWithXmlELMultiLanguageUseBaoMiDouConnSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.sql.cmp"})
|
||||
public class SQLWithXmlELMultiLanguageUseBaoMiDouConnSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testMultiLanguage1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("x2[python脚本]==>x0[if 脚本]==>a==>b", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
package com.yomahub.liteflow.test.sql;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.ds.ItemDataSource;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import com.zaxxer.hikari.HikariPoolMXBean;
|
||||
import com.zaxxer.hikari.pool.HikariPool;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -18,11 +13,6 @@ import org.springframework.test.context.TestPropertySource;
|
|||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author tangkc
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
liteflow.rule-source-ext-data={\
|
||||
"applicationName":"demo",\
|
||||
"baomidou":{"dataSourceName":"h2-first"},\
|
||||
"chainTableName":"EL_TABLE",\
|
||||
"chainApplicationNameField":"application_name",\
|
||||
"chainNameField":"chain_name",\
|
||||
"elDataField":"EL_DATA",\
|
||||
"pollingEnabled": true,\
|
||||
"pollingIntervalSeconds": 10,\
|
||||
"pollingStartSeconds": 5,\
|
||||
"scriptTableName":"script_node_table",\
|
||||
"scriptApplicationNameField":"application_name",\
|
||||
"scriptIdField":"script_node_id",\
|
||||
"scriptNameField":"script_node_name",\
|
||||
"scriptDataField":"script_node_data",\
|
||||
"scriptLanguageField":"script_language",\
|
||||
"scriptTypeField":"script_node_type"\
|
||||
}
|
||||
spring.profiles.active=test
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.datasource.dynamic.primary=h2-first
|
||||
spring.datasource.dynamic.strict=false
|
||||
spring.datasource.dynamic.datasource.h2-first.url=jdbc:h2:mem:test_db1
|
||||
spring.datasource.dynamic.datasource.h2-first.username=root1
|
||||
spring.datasource.dynamic.datasource.h2-first.password=123456
|
||||
spring.datasource.dynamic.datasource.h2-first.init.schema=classpath:/sql/schema.sql
|
||||
spring.datasource.dynamic.datasource.h2-first.init.data=classpath:/sql/data.sql
|
||||
spring.datasource.dynamic.datasource.h2-first.hikari.min-idle=1
|
||||
spring.datasource.dynamic.datasource.h2-first.hikari.max-pool-size=5
|
||||
spring.datasource.dynamic.datasource.h2-second.url=jdbc:h2:mem:test_db2
|
||||
spring.datasource.dynamic.datasource.h2-second.username=root2
|
||||
spring.datasource.dynamic.datasource.h2-second.password=123456
|
||||
spring.datasource.dynamic.datasource.h2-second.init.schema=classpath:/sql/second/schema.sql
|
||||
spring.datasource.dynamic.datasource.h2-second.init.data=classpath:/sql/second/data.sql
|
||||
spring.datasource.dynamic.datasource.h2-second.hikari.min-idle=1
|
||||
spring.datasource.dynamic.datasource.h2-second.hikari.max-pool-size=5
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>liteflow-testcase-el</artifactId>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>liteflow-testcase-el-sql-springboot-sharding-jdbc</artifactId>
|
||||
|
||||
<properties>
|
||||
<h2.version>2.1.214</h2.version>
|
||||
<jpa.version>2.6.8</jpa.version>
|
||||
<shardingsphere.version>5.5.0</shardingsphere.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-spring-boot-starter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-rule-sql</artifactId>
|
||||
<version>${revision}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<version>${jpa.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-groovy</artifactId>
|
||||
<version>${revision}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-graaljs</artifactId>
|
||||
<version>${revision}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.shardingsphere</groupId>
|
||||
<artifactId>shardingsphere-jdbc</artifactId>
|
||||
<version>${shardingsphere.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.sql.shardingjdbc;
|
||||
|
||||
|
||||
import com.yomahub.liteflow.core.FlowInitHook;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
import com.yomahub.liteflow.spi.holder.SpiFactoryInitializing;
|
||||
import com.yomahub.liteflow.spring.ComponentScanner;
|
||||
import com.yomahub.liteflow.thread.ExecutorHelper;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
|
||||
/**
|
||||
* @author tangkc
|
||||
* @since 2.8.6
|
||||
*/
|
||||
public class BaseTest {
|
||||
|
||||
@AfterAll
|
||||
public static void cleanScanCache() {
|
||||
ComponentScanner.cleanCache();
|
||||
FlowBus.cleanCache();
|
||||
ExecutorHelper.loadInstance().clearExecutorServiceMap();
|
||||
SpiFactoryInitializing.clean();
|
||||
LiteflowConfigGetter.clean();
|
||||
FlowInitHook.cleanHook();
|
||||
FlowBus.clearStat();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.yomahub.liteflow.test.sql.shardingjdbc;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/application-sharding-jdbc-data-source-xml.properties")
|
||||
@SpringBootTest(classes = SQLWithXmlELShardingJdbcDsSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.sql.shardingjdbc.cmp"})
|
||||
public class SQLWithXmlELShardingJdbcDsSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testMultiLanguage1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("x2[python脚本]==>x0[if 脚本]==>a==>b", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.sql.shardingjdbc.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.sql.shardingjdbc.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.sql.shardingjdbc.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
liteflow.rule-source-ext-data={\
|
||||
"applicationName":"demo",\
|
||||
"shardingjdbc":{"dataSourceName":"ds_1"},\
|
||||
"chainTableName":"EL_TABLE",\
|
||||
"chainApplicationNameField":"application_name",\
|
||||
"chainNameField":"chain_name",\
|
||||
"elDataField":"EL_DATA",\
|
||||
"pollingEnabled": true,\
|
||||
"pollingIntervalSeconds": 10,\
|
||||
"pollingStartSeconds": 5,\
|
||||
"scriptTableName":"script_node_table",\
|
||||
"scriptApplicationNameField":"application_name",\
|
||||
"scriptIdField":"script_node_id",\
|
||||
"scriptNameField":"script_node_name",\
|
||||
"scriptDataField":"script_node_data",\
|
||||
"scriptLanguageField":"script_language",\
|
||||
"scriptTypeField":"script_node_type"\
|
||||
}
|
||||
spring.profiles.active=test
|
||||
spring.datasource.driver-class-name=org.apache.shardingsphere.driver.ShardingSphereDriver
|
||||
|
||||
spring.datasource.url=jdbc:shardingsphere:classpath:shardingsphere.yaml
|
|
@ -0,0 +1,29 @@
|
|||
rules:
|
||||
- !SINGLE
|
||||
tables:
|
||||
- "*.*" # Load all single tables
|
||||
- !READWRITE_SPLITTING
|
||||
dataSources:
|
||||
readwrite_ds:
|
||||
writeDataSourceName: ds_2
|
||||
readDataSourceNames:
|
||||
- ds_1
|
||||
transactionalReadQueryStrategy: PRIMARY
|
||||
loadBalancerName: random
|
||||
loadBalancers:
|
||||
random:
|
||||
type: RANDOM
|
||||
|
||||
dataSources:
|
||||
ds_1:
|
||||
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
|
||||
driverClassName: org.h2.Driver
|
||||
jdbcUrl: jdbc:h2:mem:test_db1;INIT=RUNSCRIPT FROM 'classpath:sql/schema.sql'\;RUNSCRIPT FROM 'classpath:sql/data.sql'
|
||||
username: root1
|
||||
password: 123456
|
||||
ds_2:
|
||||
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
|
||||
driverClassName: org.h2.Driver
|
||||
jdbcUrl: jdbc:h2:mem:test_db2;INIT=RUNSCRIPT FROM 'classpath:sql/second/schema.sql'\;RUNSCRIPT FROM 'classpath:sql/second/data.sql'
|
||||
username: root2
|
||||
password: 123456
|
|
@ -0,0 +1,14 @@
|
|||
DELETE FROM EL_TABLE;
|
||||
|
||||
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain1','THEN(a, b, c);');
|
||||
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain2','THEN(a, b, c);');
|
||||
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain3','IF(x0, THEN(a, b));');
|
||||
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','<chain3>','IF(x0, THEN(a, b));');
|
||||
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain4','IF(x2, IF(x0, THEN(a, b)));');
|
||||
|
||||
DELETE FROM SCRIPT_NODE_TABLE;
|
||||
|
||||
INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x0','if 脚本','boolean_script','return true','groovy');
|
||||
INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x1','if 脚本','boolean_script','return false','groovy');
|
||||
|
||||
INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x2','python脚本','boolean_script','return true','js');
|
|
@ -0,0 +1,20 @@
|
|||
create table IF NOT EXISTS `EL_TABLE`
|
||||
(
|
||||
`id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
`application_name` varchar(32) NOT NULL,
|
||||
`chain_name` varchar(32) NOT NULL,
|
||||
`el_data` varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
create table IF NOT EXISTS `script_node_table`
|
||||
(
|
||||
`id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
`application_name` varchar(32) NOT NULL,
|
||||
`script_node_id` varchar(32) NOT NULL,
|
||||
`script_node_name` varchar(32) NOT NULL,
|
||||
`script_node_type` varchar(32) NOT NULL,
|
||||
`script_node_data` varchar(1024) NOT NULL,
|
||||
`script_language` varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
|
@ -0,0 +1,4 @@
|
|||
DELETE
|
||||
FROM EL_TABLE;
|
||||
DELETE
|
||||
FROM SCRIPT_NODE_TABLE;
|
|
@ -0,0 +1,20 @@
|
|||
create table IF NOT EXISTS `EL_TABLE`
|
||||
(
|
||||
`id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
`application_name` varchar(32) NOT NULL,
|
||||
`chain_name` varchar(32) NOT NULL,
|
||||
`el_data` varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
create table IF NOT EXISTS `script_node_table`
|
||||
(
|
||||
`id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
`application_name` varchar(32) NOT NULL,
|
||||
`script_node_id` varchar(32) NOT NULL,
|
||||
`script_node_name` varchar(32) NOT NULL,
|
||||
`script_node_type` varchar(32) NOT NULL,
|
||||
`script_node_data` varchar(1024) NOT NULL,
|
||||
`script_language` varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
|
@ -43,6 +43,7 @@
|
|||
<module>liteflow-testcase-el-script-kotlin-springboot</module>
|
||||
<module>liteflow-testcase-el-sql-solon</module>
|
||||
<module>liteflow-testcase-el-script-javax-springboot</module>
|
||||
<module>liteflow-testcase-el-sql-springboot-sharding-jdbc</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
|
3
pom.xml
3
pom.xml
|
@ -78,6 +78,9 @@
|
|||
<janino.version>3.1.12</janino.version>
|
||||
<kotlin.version>1.9.23</kotlin.version>
|
||||
<liquor.version>1.3.6</liquor.version>
|
||||
<!--sql plugin-->
|
||||
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
|
||||
<sharding-jdbc.version>4.1.1</sharding-jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
Loading…
Reference in New Issue