commit 40fdd3147c73891537171800a3cff9a3e9752957 Author: 少年梦与砖 <2847127106@qq.com> Date: Mon Sep 9 17:04:23 2024 +0800 初始化 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..32b6e28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/ +logs/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ffab0fb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/dragonwell:17.0.4.0.4.8-standard-ga-8.6 + +#定义时区参数 +ENV TZ=Asia/Shanghai +#设置时区 +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone + +VOLUME ["/home/logs/cloud-etl-server","/home/uploadPath"] + +#拷贝执行jar包文件 +COPY ./etl-rule-server/target/cloud-rule-engine.jar /home/app.jar + +#构建启动命令 +ENTRYPOINT ["java","-Dfile.encoding=utf-8","-jar","-Xbootclasspath/a:$toolspath/tools.jar"] +CMD ["/home/app.jar"] diff --git a/etl-rule-common/pom.xml b/etl-rule-common/pom.xml new file mode 100644 index 0000000..06fe533 --- /dev/null +++ b/etl-rule-common/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.muyu + cloud-rule-engine + 3.6.5 + + + etl-rule-common + 3.6.5 + + + 17 + 17 + UTF-8 + + + + + com.muyu + cloud-etl-common + 3.6.5 + + + com.muyu + cloud-common-core + + + + diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/BasicEngine.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/BasicEngine.java new file mode 100644 index 0000000..335979a --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/BasicEngine.java @@ -0,0 +1,22 @@ +package com.muyu.etl.rule.basic; + +import com.muyu.etl.rule.basic.handler.BasicEngineHandler; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 规则引擎基准 + * @Version 1.0.0 + */ +public interface BasicEngine { + + public void set(V value); + + public V get(); + + public default void remove() { + BasicEngineHandler.remove(); + } + + public void execution(); +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineRowActuator.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineRowActuator.java new file mode 100644 index 0000000..6a219d3 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineRowActuator.java @@ -0,0 +1,31 @@ +package com.muyu.etl.rule.basic.abstracts; + +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.basic.BasicEngine; +import com.muyu.etl.rule.basic.handler.EngineRowHandler; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 数据行处理对象 + * @Version 1.0.0 + */ +public abstract class DataEngineRowActuator implements BasicEngine { + + @Override + public void set(DataStructure[] values) { + EngineRowHandler.set(values); + } + + @Override + public DataStructure[] get() { + return EngineRowHandler.get(); + } + + @Override + public void execution() { + this.run(); + } + + public abstract void run(); +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineRowsActuator.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineRowsActuator.java new file mode 100644 index 0000000..e2e4379 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineRowsActuator.java @@ -0,0 +1,31 @@ +package com.muyu.etl.rule.basic.abstracts; + +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.basic.BasicEngine; +import com.muyu.etl.rule.basic.handler.EngineRowHandler; +import com.muyu.etl.rule.basic.handler.EngineRowsHandler; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 数据组处理对象 + * @Version 1.0.0 + */ +public abstract class DataEngineRowsActuator implements BasicEngine { + @Override + public void set(DataStructure[][] values) { + EngineRowsHandler.set(values); + } + + @Override + public DataStructure[][] get() { + return EngineRowsHandler.get(); + } + + @Override + public void execution() { + this.run(); + } + + public abstract void run(); +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineValueActuator.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineValueActuator.java new file mode 100644 index 0000000..372360a --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/abstracts/DataEngineValueActuator.java @@ -0,0 +1,34 @@ +package com.muyu.etl.rule.basic.abstracts; + +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.basic.BasicEngine; +import com.muyu.etl.rule.basic.handler.BasicEngineHandler; +import com.muyu.etl.rule.basic.handler.EngineValueHandler; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 数据值处理对象 + * @Version 1.0.0 + */ +public abstract class DataEngineValueActuator implements BasicEngine { + + + @Override + public void set(DataStructure dataStructure) { + EngineValueHandler.set(dataStructure); + } + + @Override + public DataStructure get() { + return EngineValueHandler.get(); + } + + + @Override + public void execution() { + this.run(); + } + + public abstract void run(); +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/BasicEngineHandler.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/BasicEngineHandler.java new file mode 100644 index 0000000..247bb59 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/BasicEngineHandler.java @@ -0,0 +1,24 @@ +package com.muyu.etl.rule.basic.handler; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 规则引擎作用域 + * @Version 1.0.0 + */ +public class BasicEngineHandler { + + private static final ThreadLocal threadLocal = new ThreadLocal<>(); + + public static void set(final Object handler) { + threadLocal.set(handler); + } + + public static T get() { + return (T) threadLocal.get(); + } + + public static void remove() { + + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineRowHandler.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineRowHandler.java new file mode 100644 index 0000000..4060511 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineRowHandler.java @@ -0,0 +1,27 @@ +package com.muyu.etl.rule.basic.handler; + +import com.muyu.common.core.text.Convert; +import com.muyu.etl.domain.DataStructure; + +import java.math.BigDecimal; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 行数据引擎作用域 + * @Version 1.0.0 + */ +public class EngineRowHandler { + + private static final ThreadLocal threadLocal = new ThreadLocal<>(); + + public static void set(DataStructure[] dataStructureRow){ + threadLocal.set(dataStructureRow); + } + + public static DataStructure[] get(){ + return threadLocal.get(); + } + + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineRowsHandler.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineRowsHandler.java new file mode 100644 index 0000000..e3615c4 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineRowsHandler.java @@ -0,0 +1,23 @@ +package com.muyu.etl.rule.basic.handler; + + +import com.muyu.etl.domain.DataStructure; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 数据组处理 + * @Version 1.0.0 + */ +public class EngineRowsHandler { + + private static final ThreadLocal threadLocal = new ThreadLocal<>(); + + public static void set(DataStructure[][] dataStructureRows){ + threadLocal.set(dataStructureRows); + } + + public static DataStructure[][] get(){ + return threadLocal.get(); + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineValueHandler.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineValueHandler.java new file mode 100644 index 0000000..24249a2 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/basic/handler/EngineValueHandler.java @@ -0,0 +1,56 @@ +package com.muyu.etl.rule.basic.handler; + +import com.muyu.common.core.text.Convert; +import com.muyu.etl.domain.DataStructure; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @Author WangXin + * @Data 2024/8/29 + * @Description 数据值作用域 + * @Version 1.0.0 + */ +public class EngineValueHandler { + + public static void set(DataStructure dataStructure) { + BasicEngineHandler.set(dataStructure); + } + + public static DataStructure get() { + return BasicEngineHandler.get(); + } + + public static Object getValue() { + return get().getValue(); + } + + public static Integer getIntValue() { + return Convert.toInt(getValue(), null); + } + + public static Long getLongValue() { + return Convert.toLong(getValue(), null); + } + + public static Float getFloatValue() { + return Convert.toFloat(getValue(), null); + } + + public static Double getDoubleValue() { + return Convert.toDouble(getValue(), null); + } + + public static Boolean getBooleanValue() { + return Convert.toBool(getValue(), null); + } + + public static String getStringValue() { + return Convert.toStr(getValue(), null); + } + + public static BigDecimal getBigDecimalValue() { + return Convert.toBigDecimal(getValue(), null); + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/DataStructureResp.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/DataStructureResp.java new file mode 100644 index 0000000..6599f77 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/DataStructureResp.java @@ -0,0 +1,10 @@ +package com.muyu.etl.rule.domain; + +/** + * @Author WangXin + * @Data 2024/9/1 + * @Description 参数类型 + * @Version 1.0.0 + */ +public class DataStructureResp { +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/RuleInfo.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/RuleInfo.java new file mode 100644 index 0000000..d84548d --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/RuleInfo.java @@ -0,0 +1,82 @@ +package com.muyu.etl.rule.domain; + +import com.muyu.common.core.annotation.Excel; +import com.muyu.common.core.web.domain.BaseEntity; +import lombok.*; +import lombok.experimental.SuperBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; + +/** + * 规则维护对象 etl_rule_info + * + * @author WangXin + * @date 2024-08-25 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@Setter +@Getter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@TableName("etl_rule_info") +public class RuleInfo extends BaseEntity{ + private static final long serialVersionUID = 1L; + + /** 主键 */ + @TableId( type = IdType.AUTO) + private Long id; + + /** 规则名称 */ + @Excel(name = "规则名称") + private String ruleName; + + /** 规则编码 */ + @Excel(name = "规则编码") + private String ruleCode; + + /** 规则分类 */ + @Excel(name = "规则分类") + private String ruleTypeValue; + + /** 规则级别 */ + @Excel(name = "规则级别") + private Long ruleLevelId; + + /** 是否激活(Y激活 N不激活) */ + @Excel(name = "是否激活", readConverterExp = "Y=激活,N=不激活") + private String isActivation; + + /** 规则状态(Y正常 N停用) */ + @Excel(name = "规则状态(Y正常 N停用)") + private String status; + + /** 规则说明 */ + @Excel(name = "规则说明") + private String ruleExplain; + + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("ruleName", getRuleName()) + .append("ruleCode", getRuleCode()) + .append("ruleTypeValue", getRuleTypeValue()) + .append("ruleLevelId", getRuleLevelId()) + .append("isActivation", getIsActivation()) + .append("status", getStatus()) + .append("ruleExplain", getRuleExplain()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/RuleVersion.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/RuleVersion.java new file mode 100644 index 0000000..19a5c9d --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/RuleVersion.java @@ -0,0 +1,93 @@ +package com.muyu.etl.rule.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.muyu.common.core.annotation.Excel; +import com.muyu.common.core.web.domain.BaseEntity; +import lombok.*; +import lombok.experimental.SuperBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 规则版本对象 etl_rule_version + * + * @author wangXin + * @date 2024-08-25 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@Setter +@Getter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@TableName("etl_rule_version") +public class RuleVersion extends BaseEntity{ + private static final long serialVersionUID = 1L; + + /** 版本Id */ + @TableId( type = IdType.AUTO) + private Long id; + + /** 版本类 */ + @Excel(name = "版本类") + private String ruleVersionClass; + + /** 版本名称 */ + @Excel(name = "版本名称") + private String ruleVersionName; + + /** 版本CODE */ + @Excel(name = "版本CODE") + private String ruleVersionCode; + + /** 是否激活(1激活 0未激活) */ + @Excel(name = "是否激活", readConverterExp = "Y激活,N未激活") + private String ruleVersionIsActivation; + + /** 是否测试(0未测试 1测试已通过 2测试未通过) */ + @Excel(name = "是否测试", readConverterExp = "0=未测试,1=测试已通过,2=测试未通过") + private Long ruleVersionIsTest; + + /** 版本状态(0初始化 1已发布 2未发布) */ + @Excel(name = "版本状态", readConverterExp = "0=初始化,1=已发布,2=未发布") + private Long ruleVersionStatus; + + /** 版本描述 */ + @Excel(name = "版本描述") + private String ruleVersionDescribed; + + /** 规则Id */ + private Long ruleId; + + /** 版本作用域 */ + private Integer ruleVersionScope; + + /** + * 文件内容 + */ + @TableField(exist = false) + private String classContent; + + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("ruleVersionClass", getRuleVersionClass()) + .append("ruleVersionName", getRuleVersionName()) + .append("ruleVersionCode", getRuleVersionCode()) + .append("ruleVersionIsActivation", getRuleVersionIsActivation()) + .append("ruleVersionIsTest", getRuleVersionIsTest()) + .append("ruleVersionStatus", getRuleVersionStatus()) + .append("ruleVersionDescribed", getRuleVersionDescribed()) + .append("ruleId", getRuleId()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/constants/RuleConstants.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/constants/RuleConstants.java new file mode 100644 index 0000000..8f80e94 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/constants/RuleConstants.java @@ -0,0 +1,14 @@ +package com.muyu.etl.rule.domain.constants; + +/** + * @Author WangXin + * @Data 2024/9/9 + * @Description + * @Version 1.0.0 + */ +public interface RuleConstants { + + String CLOUD_RULE_ENGINE = "cloud-rule-engine"; + + String RULE_VERSION_PATH = "ruleVersion"; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataSourceAddReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataSourceAddReq.java new file mode 100644 index 0000000..051d0aa --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataSourceAddReq.java @@ -0,0 +1,63 @@ +package com.muyu.etl.rule.domain.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @version 1.0 + * @Author xie ya ru + * @Date 2024/8/19 19:14 + * @注释 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +@Tag(name = "添加数据源信息" ,description = "数据源详细信息的添加") +public class DataSourceAddReq { + /** + * 数据源类型 + */ + @NotEmpty(message = "数据来源不可为空") + @Schema(type = "String",defaultValue = "MySQL",description = "数据信息来源的信息名称") + private String databaseType; + /** + * 数据源名称 + */ + @NotEmpty(message = "数据源名称不可为空") + @Schema(type = "String",defaultValue = "cloud-app",description = "数据源的来源的名称") + private String databaseFormName; + /** + * 数据来源地址 + */ + @NotEmpty(message = "数据来源地址不可为空") + + @Schema(type = "String",defaultValue = "127.0.0.1",description = "数据来源地址") + private String databaseUrl; + /** + * 来源地址端口号 + */ + @Schema(type = "String",defaultValue = "3306",description = "来源地址端口号") + private String databasePost; + /** + * 数据库名称 + */ + @Schema(type = "String",defaultValue = "cloud-server",description = "数据库名称") + private String databaseName; + /** + * 数据库登录名 + */ + @Schema(type = "String",defaultValue = "root",description = "数据库登录名") + private String userName; + /** + * 数据库登录密码 + */ + @Schema(type = "String",defaultValue = "wuzuxiaoniu@123.",description = "数据库登录密码") + private String userPwd; + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataSqlField.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataSqlField.java new file mode 100644 index 0000000..362ceeb --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataSqlField.java @@ -0,0 +1,25 @@ +package com.muyu.etl.rule.domain.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @Author WangXin + * @Data 2024/9/2 + * @Description + * @Version 1.0.0 + */ +@Data +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +public class DataSqlField { + + + private String columnName; + + private String rowIndex; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataTestReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataTestReq.java new file mode 100644 index 0000000..1459e00 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/DataTestReq.java @@ -0,0 +1,30 @@ +package com.muyu.etl.rule.domain.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +/** + * @Author WangXin + * @Data 2024/9/2 + * @Description 数据测试请求参数 + * @Version 1.0.0 + */ +@Data +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +public class DataTestReq { + + private Long basicId; + + private String tableName; + + private String columnName; + + private List rows; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleEngineReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleEngineReq.java new file mode 100644 index 0000000..b751fa0 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleEngineReq.java @@ -0,0 +1,25 @@ +package com.muyu.etl.rule.domain.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author WangXin + * @Data 2024/8/24 + * @Description 启动规则引擎请求 + * @Version 1.0.0 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Tag(name = "启动规则引擎请求对象", description = "获取类的权限定名进行处理") +public class EtlRuleEngineReq { + + @Schema(type = "String", defaultValue = "com.muyu.etl.rule.domain.req.DataSourceAddReq", description = "类的全限定名") + private String fullyQualifiedName; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleListReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleListReq.java new file mode 100644 index 0000000..55f8299 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleListReq.java @@ -0,0 +1,43 @@ +package com.muyu.etl.rule.domain.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description 规则列表请求参数 + * @Version 1.0.0 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Tag(name = "规则列表请求对象", description = "规则列表查询请求时所需要的条件") +public class EtlRuleListReq { + /** + * 规则名称模糊查询 + */ + @Schema(type = "String", defaultValue = "邮箱规则", description = "规则名称模糊查询") + private String ruleName; + /** + * 规则类型精确查询 + */ + @Schema(type = "String", defaultValue = "email", description = "规则类型字典精确查询") + private String ruleTypeValue; + /** + * 是否激活字典 + */ + @Schema(type = "String", description = "是否激活字典查询 Y 或者 N", defaultValue = "Y") + private String isActivation; + /** + * 规则开启和禁用的字段 Y 或者 N + */ + @Schema(type = "String", defaultValue = "Y", description = "规则开启和禁用的字段,Y或者N") + private String status; + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleSaveReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleSaveReq.java new file mode 100644 index 0000000..c1c47ef --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/EtlRuleSaveReq.java @@ -0,0 +1,43 @@ +package com.muyu.etl.rule.domain.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description 规则添加请求参数 + * @Version 1.0.0 + */ +@Data +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +@Tag(name = "规则添加请求对象" ,description = "规则添加请求时所需要的条件") +public class EtlRuleSaveReq { + + /** 规则名称 */ + @Schema(type = "String", defaultValue = "not_null_rule", description = "定义唯一的规则名称",requiredProperties = "true") + private String ruleName; + + /** 规则分类 */ + @Schema(type = "Long", defaultValue = "1", description = "定义规则类型Id",requiredProperties = "true") + private Long ruleTypeId; + + /** 规则说明 */ + @Schema(type = "String", defaultValue = "非空校验", description = "规则描述",requiredProperties = "true") + private String ruleExplain; + + /** 规则类权限定名 */ + @Schema(type = "String", defaultValue = "com.muyu.etl.rule.domain.req.EtlRuleEngineReq", description = "规则所在类的全限定名",requiredProperties = "true") + private String fullyQualifiedName; + + /** 是否公开(Y.公开 Y.不公开) */ + @Schema(type = "String", defaultValue = "Y", description = "规则启动/停止",requiredProperties = "true") + private String status; + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/ExecutionRuleVersionReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/ExecutionRuleVersionReq.java new file mode 100644 index 0000000..6223c50 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/ExecutionRuleVersionReq.java @@ -0,0 +1,34 @@ +package com.muyu.etl.rule.domain.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.HashMap; + +/** + * @Author WangXin + * @Data 2024/8/27 + * @Description 执行规则请求对象 + * @Version 1.0.0 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Tag(name = "执行规则请求对象", description = "执行规则请求所需的参数和类名") +public class ExecutionRuleVersionReq { + /** + * 类名 + */ + @Schema(description = "执行的类名", defaultValue = "engine_custom_email_IAW3S02", requiredProperties = "true") + private String engineKey; + /** + * 参数集合 + */ + @Schema(description = "执行方法所需的参数", requiredProperties = "true") + private HashMap params; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/WriteFileReq.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/WriteFileReq.java new file mode 100644 index 0000000..b725f58 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/req/WriteFileReq.java @@ -0,0 +1,37 @@ +package com.muyu.etl.rule.domain.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author WangXin + * @Data 2024/8/27 + * @Description 写入请求对象 + * @Version 1.0.0 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Tag(name = "文件写入请求对象", description = "编写规则类时写入文件进行持久化保存") +public class WriteFileReq { + + /** + * 请求文件名 + */ + @Schema(description = "存入的文件名", defaultValue = "engine_email-rule_JISID8S", requiredProperties = "true") + @NotEmpty(message = "文件名不能为空") + private String fileName; + /** + * 写入内容 + */ + @Schema(description = "存入的文件内容", defaultValue = "...", requiredProperties = "true") + @NotEmpty(message = "文件内容不能为空") + private String content; +} + diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/resp/EtlRuleListResp.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/resp/EtlRuleListResp.java new file mode 100644 index 0000000..67daa59 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/domain/resp/EtlRuleListResp.java @@ -0,0 +1,72 @@ +package com.muyu.etl.rule.domain.resp; + +import com.muyu.etl.rule.domain.RuleInfo; +import com.muyu.etl.rule.domain.RuleVersion; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; +import java.util.function.Supplier; + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description etl数据列表响应对象 + * @Version 1.0.0 + */ +@Data +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +@Tag(name = "规则列表响应对象",description = "查询规则列表信息需要输出的字段") +public class EtlRuleListResp { + /** 主键 */ + @Schema(type = "Long", defaultValue = "1", description = "规则主键",requiredProperties = "true") + private Long id; + /** 规则名称 */ + @Schema(type = "String",defaultValue = "脱敏规则",description = "规则名称") + private String ruleName; + /** 规则编码 */ + @Schema(type = "String",defaultValue = "tel_desensitization_rule",description = "规则名称") + private String ruleCode; + /** 规则分类 */ + @Schema(type = "String",defaultValue = "system",description = "规则分类(字典字段)") + private String ruleTypeValue; + /** 规则说明 */ + @Schema(type = "String",defaultValue = "对手机号进行脱敏处理",description = "规则说明") + private String ruleExplain; + + /** 规则状态(Y正常 N停用) */ + @Schema(type = "String",defaultValue = "Y",description = "规则状态(Y正常 N停用)") + private String status; + + /** 规则级别 */ + @Schema(type = "String",defaultValue = "",description = "规则级别") + private Long ruleLevelId; + + /** 是否激活(Y激活 N不激活) */ + @Schema(type = "String",defaultValue = "N",description = "是否激活(Y=激活,N=不激活)") + private String isActivation; + /** 规则版本列表 */ + @Schema(type = "List", description = "规则版本列表") + private List ruleVersionList; + + public static EtlRuleListResp buildEtlRuleListResp(RuleInfo ruleInfo, List list) { + return EtlRuleListResp.builder() + .id(ruleInfo.getId()) + .ruleName(ruleInfo.getRuleName()) + .ruleCode(ruleInfo.getRuleCode()) + .ruleTypeValue(ruleInfo.getRuleTypeValue()) + .ruleExplain(ruleInfo.getRuleExplain()) + .status(ruleInfo.getStatus()) + .ruleLevelId(ruleInfo.getRuleLevelId()) + .isActivation(ruleInfo.getIsActivation()) + .ruleVersionList(list) + .build(); + } + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/bean/annotation/EngineParam.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/bean/annotation/EngineParam.java new file mode 100644 index 0000000..9a1f143 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/bean/annotation/EngineParam.java @@ -0,0 +1,15 @@ +package com.muyu.etl.rule.engine.bean.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface EngineParam { + /** + * 输入字段的名称 + */ + public String name() default ""; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/bean/constant/FileConstants.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/bean/constant/FileConstants.java new file mode 100644 index 0000000..02e5b87 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/bean/constant/FileConstants.java @@ -0,0 +1,13 @@ +package com.muyu.etl.rule.engine.bean.constant; + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description 文件相关常量 + * @Version 1.0.0 + */ +public interface FileConstants { + String JAVA_SUFFIX = ".java"; + String CLASS_SUFFIX = ".class"; + String FILE_DELIMITER = System.getProperty("os.name").contains("Windows") ? "\\" : "/"; +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/EngineContainer.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/EngineContainer.java new file mode 100644 index 0000000..c13f04f --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/EngineContainer.java @@ -0,0 +1,124 @@ +package com.muyu.etl.rule.engine.core; + + + +import com.muyu.etl.rule.engine.bean.annotation.EngineParam; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @Author WangXin + * @Data 2024/8/23 + * @Descriptio + * @Version 1.0.0 + */ + +public class EngineContainer { + + private static final Logger log = LogManager.getLogger(EngineContainer.class.getName()); + + public final static ConcurrentHashMap instanceMap = new ConcurrentHashMap<>(16); + + private final static ConcurrentHashMap> classMap = new ConcurrentHashMap<>(16); + + private final static ConcurrentHashMap methodMap = new ConcurrentHashMap<>(16); + + private final static ConcurrentHashMap> methodEngineParamMap = new ConcurrentHashMap<>(16); + + public static void loadEngineInstance(String methodName, String engineKey, Class aClass) { + + Method method = findByMethodByClass(methodName, aClass); + + List engineParams = new ArrayList<>(); + + try { + instanceMap.put(engineKey, aClass.newInstance()); + log.info("[{}]类实例化成功---》class:{}",engineKey,aClass.getName()); + } catch (InstantiationException e) { + log.error("[类实例化错误]--- {}", e.getMessage(), e); + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + log.error("[类实例化错误]--- {}", e.getMessage(), e); + throw new RuntimeException(e); + } + + classMap.put(engineKey, aClass); + methodMap.put(engineKey, method); + //获取方法所有参数类型 + Class[] parameterTypes = method.getParameterTypes(); + if (parameterTypes.length == 0) { + log.info("{}--》方法没有参数", methodName); + return; + } + //获取方法参数注解 + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + //获取参数 + for (int i = 0; i < parameterTypes.length; i++) { + Annotation[] parameterAnnotation = parameterAnnotations[i]; + if (parameterAnnotation.length == 0) { + log.error("请给所有参数添加注解"); + throw new RuntimeException("请给所有参数添加注解"); + } + if (parameterAnnotation.length > 1) { + log.error("参数只能有一个注解"); + throw new RuntimeException("参数只能有一个注解"); + } + EngineParam engineParam = null; + if (parameterAnnotation[0] instanceof EngineParam) { + engineParam = (EngineParam) parameterAnnotation[0]; + } + if (engineParam == null) { + throw new RuntimeException("请使用EngineParam注解"); + } else if (engineParam.name() != null && engineParam.name().isEmpty()) { + throw new RuntimeException("EnginParam注解的name参数不能为空"); + } + engineParams.add(engineParam.name()); + } + methodEngineParamMap.put(engineKey, engineParams); + log.info("初始化规则引擎成功---》规则引擎名称:{} ,执行方法:{},参数:{}", engineKey, method.getName(), engineParams.toString()); + } + + /** + * 通过方法名判断类中是否有此方法 + * + * @param methodName 方法名 + * @param aClass 类的class对象 + * @return 如果有方法则返回此方法的method对象,没有则报错 + */ + private static Method findByMethodByClass(String methodName, Class aClass) { + Method method = null; + for (Method aMethod : aClass.getMethods()) { + if (aMethod.getName().equals(methodName)) { + method = aMethod; + } + } + if (method == null) { + log.info("[{}] 类中没有 [{}] 方法", aClass.getName(), methodName); + throw new RuntimeException("Method not found: " + methodName); + } else { + return method; + } + } + + public static Object getInstance(String engineKey) { + return instanceMap.get(engineKey); + } + + public static Method getMethodByClass(String engineKey) { + return methodMap.get(engineKey); + } + + public static List getMethodEngineParam(String engineKey) { + return methodEngineParamMap.get(engineKey); + } + + public static Class getClassByEngineKey(String engineKey) { + return classMap.get(engineKey); + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/EngineExecution.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/EngineExecution.java new file mode 100644 index 0000000..940bf68 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/EngineExecution.java @@ -0,0 +1,82 @@ +package com.muyu.etl.rule.engine.core; + +import com.muyu.etl.rule.engine.core.EngineContainer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @Author WangXin + * @Data 2024/8/23 + * @Description 规则引擎方法执行器 + * @Version 1.0.0 + */ + +public class EngineExecution { + + private static final Logger log = LogManager.getLogger(EngineExecution.class.getName()); + + /** + * 有参method执行器 + * @param engineKey 引擎名称 + * @param params 参数 + * @return 方法调用结果 + */ + public static Object argumentEngineExe(String engineKey, Map params){ + + Object instance = EngineContainer.getInstance(engineKey); + Method method = EngineContainer.getMethodByClass(engineKey); + List methodEngineParam = EngineContainer.getMethodEngineParam(engineKey); + + + try { + int methodParamLength = methodEngineParam.size(); + Object[] objects = new Object[methodParamLength]; + for (int i = 0; i < methodParamLength; i++) { + objects[i] = params.get(methodEngineParam.get(i)); + } + log.info("规则引擎 [{}] 调用参数 [{}]",engineKey, Arrays.toString(objects)); + Object invoke = method.invoke(instance, objects); + log.info("规则引擎 [{}] 调用结果 [{}] ",engineKey, Arrays.toString(objects)); + return invoke; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + /** + * 有参method执行器 + * @param engineKey 引擎名称 + * @return 方法调用结果 + */ + public static Object noArgumentEngineExe(String engineKey){ + + Object instance = EngineContainer.getInstance(engineKey); + Method method = EngineContainer.getMethodByClass(engineKey); + List methodEngineParam = EngineContainer.getMethodEngineParam(engineKey); + int methodParamLength = methodEngineParam.size(); + if (methodParamLength != 0){ + log.info("[方法名错误] 此方法为有参方法请选择 [argumentEngineExe] 方法输入对应参数"); + throw new RuntimeException("[方法名错误] 此方法为有参方法请选择 [argumentEngineExe] 方法输入对应参数"); + } + try { + log.info("规则引擎 [{}] 启动",engineKey); + Object invoke = method.invoke(instance); + log.info("规则引擎 [{}] invoke 调用成功",engineKey); + return invoke; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/classLoad/ExternalClassLoader.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/classLoad/ExternalClassLoader.java new file mode 100644 index 0000000..20a75df --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/classLoad/ExternalClassLoader.java @@ -0,0 +1,29 @@ +package com.muyu.etl.rule.engine.core.classLoad; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * @Author WangXin + * @Data 2024/9/4 + * @Description 自定义classloader + * @Version 1.0.0 + */ +public class ExternalClassLoader extends URLClassLoader { + + public ExternalClassLoader(URL[] urls) { + super(urls, Thread.currentThread().getContextClassLoader()); + } + + public Class defineClassFromBytes(byte[] classBytes, String className) throws IOException { + return super.defineClass(className, classBytes, 0, classBytes.length); + } + + public Class loadClassFromPath(Path classFilePath, String className) throws IOException { + byte[] classData = Files.readAllBytes(classFilePath); + return defineClassFromBytes(classData, className); + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/classLoad/JavaBinaryClassLoader.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/classLoad/JavaBinaryClassLoader.java new file mode 100644 index 0000000..b7f390a --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/classLoad/JavaBinaryClassLoader.java @@ -0,0 +1,133 @@ +package com.muyu.etl.rule.engine.core.classLoad; + +import com.alibaba.fastjson2.JSON; +import com.muyu.etl.rule.engine.bean.constant.FileConstants; + +import com.muyu.etl.rule.engine.util.FileLoadUtil; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description java 字节码文件 加载器 + * @Version 1.0.0 + */ +public class JavaBinaryClassLoader extends ClassLoader { + + private static final Logger log = LogManager.getLogger(JavaBinaryClassLoader.class.getName()); + + private static final JavaBinaryClassLoader loader = new JavaBinaryClassLoader(); + + /** + * 自定义路径获取类的class对象 + * + * @param name 类名 + * @param pack 包名 + * @param locationFile 文件地址 + * @return class对象 + */ + private static Class loadClassByNameAndLocation(String name, String pack, File locationFile) { + //将class文件的数据读入到byte数组中 + byte[] datas = loader.loadClassData(name, locationFile); + //通过byte数组加载Class对象 + Class aClass = loader.defineClass(pack + name, datas, 0, datas.length); + log.info("成功加载规则引擎 -- {}", aClass.getName()); + return aClass; + } + + + /** + * @param pack 类所在的包名 com.muyu.bean. 后面需要带个点 + * @param location 包所在路径 + * @return + */ + public static Map> loadClassByLocation(String pack, String location) { + //列出所有的class文件 + List classFiles = FileLoadUtil.getClassFiles(location + FileConstants.FILE_DELIMITER + pack.replaceAll("\\.", FileConstants.FILE_DELIMITER)); + log.info("class文件---->{}", JSON.toJSONString(classFiles)); + HashMap> map = new HashMap<>(); + classFiles.forEach(file -> { + String name = file.getName().substring(0, file.getName().lastIndexOf(FileConstants.CLASS_SUFFIX)); +// Class c = loadClassByNameAndLocation(name, pack + ".", new File(location+ FileConstants.FILE_DELIMITER +pack.replaceAll("\\.",FileConstants.FILE_DELIMITER))); + try { + log.info("转class对象请求入参---》name:{},pack:{},path:{}", name, pack, file.getAbsolutePath()); + Class value = urlLoadClassByNameAndLocation(name, pack, file.getAbsolutePath()); + map.put(name, value); + } catch (IOException e) { + throw new RuntimeException(e); + } + + }); + return map; + } + + /** + * 将文件转换成字节数组 + * + * @param name 文件名称 + * @param locationFile 文件 + * @return 字节数组 + */ + public byte[] loadClassData(String name, File locationFile) { + byte[] byteArray = null; + try { + FileInputStream fis = new FileInputStream(locationFile + FileConstants.FILE_DELIMITER + name + FileConstants.CLASS_SUFFIX); + // 创建ByteArrayOutputStream对象 + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + // 创建一个缓冲区 + byte[] buffer = new byte[1024]; + int length; + // 读取文件内容并写入缓冲区 + while ((length = fis.read(buffer)) != -1) { + bos.write(buffer, 0, length); + } + // 将缓冲区中的内容转换为byte数组 + byteArray = bos.toByteArray(); + } catch (IOException e) { + log.error("[【{}】文件转换成字节数组错误]:{}", name, e.getMessage(), e); + throw new RuntimeException(e); + } + return byteArray; + } + + /** + * 自定义路径获取类的class对象 + * + * @param name 类名 + * @param pack 包名 + * @param path 文件地址 + * @return class对象 + */ + private static Class urlLoadClassByNameAndLocation(String name, String pack, String path) throws IOException { + Path classFilePath = Paths.get(path); + URL[] urls = new URL[]{new File(path).toURI().toURL()}; + ExternalClassLoader externalClassLoader = new ExternalClassLoader(urls); + // 注意类名必须是完全限定名(包括包名) + log.info("[externalClassLoader]请求入参---》classPath:{},className:{}", classFilePath, pack + "." + name); + Class clazz = externalClassLoader.loadClassFromPath(classFilePath, pack + "." + name); + return clazz; + } + + public static void main(String[] args) { + File file = new File("D:\\idea_data\\ETL\\RuleEngine\\src\\main\\java\\com\\muyu\\engine\\core\\classLoad\\ExternalClassLoader.java"); + String path = file.getPath(); + String absolutePath = file.getAbsolutePath(); + System.out.println(path); + System.out.println(absolutePath.substring(0, absolutePath.lastIndexOf(FileConstants.CLASS_SUFFIX))); + } + + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/complier/SourceCodeCompiler.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/complier/SourceCodeCompiler.java new file mode 100644 index 0000000..b4714e1 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/core/complier/SourceCodeCompiler.java @@ -0,0 +1,106 @@ +package com.muyu.etl.rule.engine.core.complier; + +import com.muyu.etl.rule.engine.bean.constant.FileConstants; +import com.muyu.etl.rule.engine.util.FileLoadUtil; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import java.io.File; +import java.util.Arrays; +import java.util.List; + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description java源码编译工具 + * @Version 1.0.0 + */ +public class SourceCodeCompiler { + + private static final Logger log = LogManager.getLogger(SourceCodeCompiler.class.getName()); + /** + * 获取系统java编译器 + */ + private static JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + /** + * 获取java文件管理器 + */ + private static StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + + private final static String workPath = System.getProperty("user.dir"); + + /** + * 输入编译的文件夹路径 + * + * @param path 路径 + */ + public static void javaCompilerPath(String path) { + List javaFiles = FileLoadUtil.getJavaFiles(path); + File[] array = javaFiles.toArray(new File[javaFiles.size()]); + javaCompiler(path, array); + } + + public static void javaCompilerFile(String... filePath) { + int filePathLength = filePath.length; + File[] files = new File[filePathLength]; + for (int i = 0; i < filePathLength; i++) { + files[i] = new File(filePath[i]); + } + javaCompiler("filePath", files); + } + + /** + * 可同时编译多个java源代码 + * + * @param file 文件 + */ + public static void javaCompiler(String path, File... file) { + //通过源文件获取到要编译的Java源代码迭代器,包括所有内部类,其中每个类都是一个JavaFileObject,也被称为一个汇编单元 + // 使用文件对象管理器来获取文件 + Iterable javaFileObjects = fileManager.getJavaFileObjects(file); + //生成编译任务 + log.info("程序运行地址为: {}", path); + List options = Arrays.asList("-classpath", path, "-verbose", "-d", path); + JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, javaFileObjects); + //执行编译任务 + Boolean call = task.call(); + + if (call) { + log.info("[{}个文件编译成功]", file.length); + } else { + throw new RuntimeException("[{}文件编译失败]: Compilation failed"); + } + } + + /** + * 可同时编译多个java源代码 + */ + public static void javaCompiler(String classConfigPath, String classpath, String javaPath, String engineKey) { + //通过源文件获取到要编译的Java源代码迭代器,包括所有内部类,其中每个类都是一个JavaFileObject,也被称为一个汇编单元 + // 使用文件对象管理器来获取文件 + log.info("[开始编译] 请求参数 -----》 classConfigPath:{} --- classpath:{} --- javaPath:{} --- engineKey:{}", classConfigPath, classpath, javaPath, engineKey); + String javaFilePath = javaPath + FileConstants.FILE_DELIMITER + engineKey + FileConstants.JAVA_SUFFIX; + log.info("[java文件路径] ---> {}}", javaFilePath); + // 构建编译参数数组 + String[] options = { + "-classpath", classConfigPath, + "-verbose", + "-d", classpath, + javaFilePath + }; + log.info("[构建编译参数数组成功] ---> {}}", Arrays.toString(options)); + // 创建编译任务 + int run = compiler.run(null, null, null, options); + // 关闭文件管理器 + + if (run==0) { + log.info("[文件编译成功]"); + } else { + throw new RuntimeException(String.format("[{}文件编译失败]: Compilation failed",engineKey)); + } + } +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/util/FileLoadUtil.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/util/FileLoadUtil.java new file mode 100644 index 0000000..b997a2b --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/util/FileLoadUtil.java @@ -0,0 +1,197 @@ +package com.muyu.etl.rule.engine.util; + +import com.alibaba.fastjson2.JSONObject; +import com.muyu.etl.rule.engine.bean.constant.FileConstants; +import com.muyu.etl.rule.engine.core.complier.SourceCodeCompiler; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.*; +import java.util.Arrays; +import java.util.List; + +/** + * @Author WangXin + * @Data 2024/8/22 + * @Description 文件扫描 + * @Version 1.0.0 + */ + +public class FileLoadUtil { + + private static final Logger log = LogManager.getLogger(SourceCodeCompiler.class.getName()); + + /** + * 判断文件是否存在 + * + * @param file 文件 + * @return 存在返回文件不存在报错 + */ + public static File isFilePresence(File file) { + if (file.exists()) { + return file; + } + log.error("[文件路径错误]"); + throw new RuntimeException("[文件路径错误]"); + } + + public static File[] isFilesExist(File[] files) { + if (files == null || files.length == 0) { + log.error("该文件夹下没有文件,请创建文件"); + throw new RuntimeException("该文件夹下没有文件,请创建文件"); + } + return files; + } + + /** + * 通过文件路径获取该文件夹下的所有文件 + * + * @param folderPath 文件夹路径 + * @return java文件 + */ + public static List getJavaFiles(String folderPath) { + File folder = new File(folderPath); + if (!folder.exists()) { + folder.mkdirs(); + } + File[] files = folder.listFiles(); + return Arrays.stream(isFilesExist(files)).filter(FileLoadUtil::isFileType).toList(); + } + + /** + * 通过文件路径获取该文件夹下的所有文件 + * + * @param folderPath 文件夹路径 + * @return class文件 + */ + public static List getClassFiles(String folderPath) { + File folder = new File(folderPath); + if (!folder.exists()) { + folder.mkdirs(); + } + File[] files = folder.listFiles(); + List list = Arrays.stream(isFilesExist(files)).filter(FileLoadUtil::isClassFileType).toList(); + log.info("[{}]路劲下的class文件有[{}]", folderPath, JSONObject.toJSONString(list)); + return list; + } + + /** + * 判断java文件类型 + * + * @param file 文件 + * @return 布尔类型的值 + */ + public static Boolean isFileType(File file) { + return file.getName().endsWith(FileConstants.JAVA_SUFFIX); + } + + /** + * 判断class文件类型 + * + * @param file 文件 + * @return 布尔类型的值 + */ + public static Boolean isClassFileType(File file) { + return file.getName().endsWith(FileConstants.CLASS_SUFFIX); + } + + /** + * 创建java文件 + */ + public static File createJavaFile(String filePath, String fileName) { + filePath = filePath + FileConstants.FILE_DELIMITER + fileName.split("_")[0]; + File file = new File(filePath); + if (!(file.exists() && file.isDirectory())) { + log.info("创建的文件夹:{}", filePath); + //创建文件夹 + boolean mkdirs = file.mkdirs(); + log.info("创建文件夹{}", mkdirs ? "成功" : "失败"); + } + filePath = filePath + FileConstants.FILE_DELIMITER + fileName + FileConstants.JAVA_SUFFIX; + File classFile = new File(filePath); + if (!(classFile.exists() && classFile.isFile())) { + try { + log.info("创建的文件:{}", filePath); + boolean newFile = classFile.createNewFile(); + log.info("创建文件{}", newFile ? "成功" : "失败"); + } catch (IOException e) { + log.error("创建 [{}] 文件失败 --> {}", fileName, e.getMessage(), e); + throw new RuntimeException(e); + } + } + return classFile; + } + + /** + * 写文件 + */ + public static void writeFile(String filePath, String fileName, String content) { + log.info("写文件 ---> 入参:[filePath:{},fileName:{},content{}]", filePath, fileName, content); + File javaFile = createJavaFile(filePath, fileName); + try { + BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(javaFile)); + bufferedWriter.write(content); + bufferedWriter.flush(); + bufferedWriter.close(); + } catch (IOException e) { + log.error("保存[{}]文件失败 ---> {}", fileName, e.getMessage(), e); + throw new RuntimeException(e); + } + } + + /** + * 读文件 + */ + public static String readFile(String filePath, String fileName) { + try { + File file = new File(filePath + FileConstants.FILE_DELIMITER + fileName.split("_")[0] + FileConstants.FILE_DELIMITER + fileName + FileConstants.JAVA_SUFFIX); + BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); + String content = ""; + String len; + while ((len = bufferedReader.readLine()) != null) { + content += len + "\n"; + } + return content; + } catch (Exception e) { + log.error("读取[{}]文件失败 ---> {}", fileName, e.getMessage(), e); + return ""; + } + } + + public static void main(String[] args) { + + String str = "package com.muyu.rule.test;\n" + + "\n" + + "import com.muyu.etl.rule.engine.bean.annotation.EngineParam;\n" + + "import org.apache.logging.log4j.LogManager;\n" + + "import org.apache.logging.log4j.Logger;\n" + + "\n" + + "/**\n" + + " * @Author WangXin\n" + + " * @Data 2024/8/23\n" + + " * @Description\n" + + " * @Version 1.0.0\n" + + " */\n" + + "public class XieYaRu {\n" + + "\n" + + " private static final Logger log = LogManager.getLogger(XieYaRu.class.getName());\n" + + "\n" + + " public String test(@EngineParam(name = \"phone\") String phone,@EngineParam(name = \"pat\") String pat){\n" + + " log.info(\"程序入参:phone -> {} ,pat -> {}\",phone,pat);\n" + + " if (phone.matches(pat)){\n" + + " return phone;\n" + + " }else {\n" + + " throw new RuntimeException(\"手机号格式错误\");\n" + + " }\n" + + "\n" + + " }\n" + + "}"; + + writeFile("C:\\Users\\wx\\Desktop\\测试", "XieYaRu", str); + + String xieYaRu = readFile("C:\\Users\\wx\\Desktop\\测试", "XieYaRu"); + + System.out.println(xieYaRu); + } + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/util/PropertiesUtil.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/util/PropertiesUtil.java new file mode 100644 index 0000000..b59b5fb --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/engine/util/PropertiesUtil.java @@ -0,0 +1,54 @@ +package com.muyu.etl.rule.engine.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @ClassName: PropertiesUtil + * @Description: 读取配置文件工具类 + * @author: wangXin + * @date: 2024/6/18 19:45 + * @Version 1.0.0 + */ +public class PropertiesUtil { + private static final Properties props = new Properties(); + private static final Map PROPER_MAP = new ConcurrentHashMap<>(); + + static { + + InputStream is = null; + try { + is = PropertiesUtil.class.getClassLoader().getResourceAsStream("application.properties"); + props.load(is); + + Iterator iterator = props.keySet().iterator(); + while (iterator.hasNext()) { + String key = (String) iterator.next(); + PROPER_MAP.put(key, props.getProperty(key)); + } + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + public static String getProperty(String key) { + return PROPER_MAP.get(key); + } + + public static void main(String[] args) { + System.out.println(getProperty("db.username")); + } + +} diff --git a/etl-rule-common/src/main/java/com/muyu/etl/rule/util/EnginePackUtil.java b/etl-rule-common/src/main/java/com/muyu/etl/rule/util/EnginePackUtil.java new file mode 100644 index 0000000..4bfa4a7 --- /dev/null +++ b/etl-rule-common/src/main/java/com/muyu/etl/rule/util/EnginePackUtil.java @@ -0,0 +1,38 @@ +package com.muyu.etl.rule.util; + +import com.muyu.etl.rule.basic.BasicEngine; +import com.muyu.etl.rule.basic.abstracts.DataEngineValueActuator; + +/** + * @Author WangXin + * @Data 2024/8/24 + * @Description 规则引擎全限定名转换 + * @Version 1.0.0 + */ +public class EnginePackUtil { + /** + * 获取全限定名的包名 + * @param fullyQualifiedName 全限定名 + * @return 包名 + */ + public static String getEnginePack(String fullyQualifiedName) { + return fullyQualifiedName.substring(0,fullyQualifiedName.lastIndexOf(".")); + } + + /** + * 获取全限定名的类名 + * @param fullyQualifiedName 全限定名 + * @return 类名 + */ + public static String getEngineClass(String fullyQualifiedName) { + return fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf(".") + 1); + } + + public static void main(String[] args) { + + String enginePack = getEnginePack("com.muyu.etl.rule.domain.req.DataSourceAddReq"); + System.out.println(enginePack); + String engineClass = getEngineClass("com.muyu.etl.rule.domain.req.DataSourceAddReq"); + System.out.println(engineClass); + } +} diff --git a/etl-rule-remote/pom.xml b/etl-rule-remote/pom.xml new file mode 100644 index 0000000..dea95a8 --- /dev/null +++ b/etl-rule-remote/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + com.muyu + cloud-rule-engine + 3.6.5 + + + etl-rule-remote + 3.6.5 + + + 17 + 17 + UTF-8 + + + + + com.muyu + etl-rule-common + 3.6.5 + + + + diff --git a/etl-rule-remote/src/main/java/com/muyu/etl/rule/remote/RemoteRuleVersion.java b/etl-rule-remote/src/main/java/com/muyu/etl/rule/remote/RemoteRuleVersion.java new file mode 100644 index 0000000..ed83c4e --- /dev/null +++ b/etl-rule-remote/src/main/java/com/muyu/etl/rule/remote/RemoteRuleVersion.java @@ -0,0 +1,28 @@ +package com.muyu.etl.rule.remote; + +import com.muyu.common.core.domain.Result; +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.domain.constants.RuleConstants; +import com.muyu.etl.rule.remote.factory.RemoteRuleVersionBackFactory; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * @version 1.0 + * @Author xie ya ru + * @Date 2024/9/2 14:35 + * @注释 + */ +@FeignClient(contextId = "remoteRuleVersion", + value = RuleConstants.CLOUD_RULE_ENGINE, + path = RuleConstants.RULE_VERSION_PATH, + fallbackFactory = RemoteRuleVersionBackFactory.class) +public interface RemoteRuleVersion { + + + @PostMapping("/groupFile/{engineKey}") + public Result executionGroupRuleVersion(@PathVariable("engineKey") String engineKey, @RequestBody DataStructure[][] dataStructureRows); + +} diff --git a/etl-rule-remote/src/main/java/com/muyu/etl/rule/remote/factory/RemoteRuleVersionBackFactory.java b/etl-rule-remote/src/main/java/com/muyu/etl/rule/remote/factory/RemoteRuleVersionBackFactory.java new file mode 100644 index 0000000..cd7770c --- /dev/null +++ b/etl-rule-remote/src/main/java/com/muyu/etl/rule/remote/factory/RemoteRuleVersionBackFactory.java @@ -0,0 +1,32 @@ +package com.muyu.etl.rule.remote.factory; + +import com.muyu.common.core.domain.Result; +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.remote.RemoteRuleVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + +/** + * @version 1.0 + * @Author xie ya ru + * @Date 2024/9/1 10:04 + * @注释 + */ +@Component +public class RemoteRuleVersionBackFactory implements FallbackFactory { + private static final Logger log = LoggerFactory.getLogger(RemoteRuleVersionBackFactory.class); + + @Override + public RemoteRuleVersion create(Throwable cause) { + log.error("文件服务调用失败:{}", cause.getMessage()); + + return new RemoteRuleVersion() { + @Override + public Result executionGroupRuleVersion(String engineKey, DataStructure[][] dataStructureRows) { + return Result.error("查询数据失败:"+cause.getMessage()); + } + }; + } +} diff --git a/etl-rule-remote/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/etl-rule-remote/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..c214774 --- /dev/null +++ b/etl-rule-remote/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.muyu.etl.rule.remote.factory.RemoteRuleVersionBackFactory diff --git a/etl-rule-server/pom.xml b/etl-rule-server/pom.xml new file mode 100644 index 0000000..3e2d2f7 --- /dev/null +++ b/etl-rule-server/pom.xml @@ -0,0 +1,128 @@ + + + 4.0.0 + + com.muyu + cloud-rule-engine + 3.6.5 + + + etl-rule-server + 3.6.5 + + + 17 + 17 + UTF-8 + + + + + + com.muyu + cloud-common-core + + + com.muyu + etl-datasource-remote + 3.6.5 + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.mysql + mysql-connector-j + + + + + com.muyu + cloud-common-datasource + + + + + com.muyu + cloud-common-datascope + + + + + com.muyu + cloud-common-log + + + + + com.muyu + cloud-common-xxl + + + com.muyu + etl-rule-common + 3.6.5 + + + + + cloud-rule-engine + + + org.springframework.boot + spring-boot-maven-plugin + 3.2.6 + + + + repackage + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/ENGINE_NOT_NULL_NAME_V1.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/ENGINE_NOT_NULL_NAME_V1.java new file mode 100644 index 0000000..3810cf2 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/ENGINE_NOT_NULL_NAME_V1.java @@ -0,0 +1,33 @@ +package com.muyu.etl.rule; + +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.basic.abstracts.DataEngineRowsActuator; +import com.muyu.etl.rule.operation.ArrayUtil; + +import java.util.Arrays; +import java.util.List; + +/** + * @Author WangXin + * @Data Mon Sep 09 2024 01:04:05 GMT+0800 (中国标准时间) + * @Description null + * @Version 1.0.0 + */ +public class ENGINE_NOT_NULL_NAME_V1 extends DataEngineRowsActuator { + + + @Override + public void run() { + DataStructure[][] dataStructuresList = get(); + + ArrayUtil arrayUtil = new ArrayUtil<>(dataStructuresList); + while (arrayUtil.hasNext()){ + DataStructure[] dataStructures = arrayUtil.next(); + List dataStructureList = Arrays.stream(dataStructures).filter(dataStructure -> dataStructure.getKey().equals("name") && dataStructure.getValue() == null).toList(); + if (dataStructureList.size() > 0){ + arrayUtil.remove(); + } + } + set(arrayUtil.getCurrentArray()); + } +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/EtlRuleEngineApplication.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/EtlRuleEngineApplication.java new file mode 100644 index 0000000..a2204e5 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/EtlRuleEngineApplication.java @@ -0,0 +1,17 @@ +package com.muyu.etl.rule; + +import com.muyu.common.security.annotation.EnableCustomConfig; +import com.muyu.common.security.annotation.EnableMyFeignClients; +import groovy.util.logging.Log4j2; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@Log4j2 +@EnableCustomConfig +@EnableMyFeignClients +@SpringBootApplication +public class EtlRuleEngineApplication { + public static void main(String[] args) { + SpringApplication.run(EtlRuleEngineApplication.class, args); + } +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/config/EngineConfig.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/config/EngineConfig.java new file mode 100644 index 0000000..d3f8f13 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/config/EngineConfig.java @@ -0,0 +1,52 @@ +package com.muyu.etl.rule.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @Author WangXin + * @Data 2024/8/27 + * @Description 规则配置类 + * @Version 1.0.0 + */ +@Configuration +@ConfigurationProperties(prefix = "engine") +@Data +public class EngineConfig { + //执行方法名 + public String methodName; + //操作地址 + public String sourceLocation; + //编译地址 + public String classConfigPath; + //包名 + public String packageName; + //window地址源地址 + public String windowSourceLocation; + //linux源地址 + public String linuxSourceLocation; + //window class文件配置地址 + public String windowsClassConfigPath; + //linux class文件配置地址 + public String linuxClassConfigPath; + + + @Bean + public EngineConfig initengineConfig() { + //获取系统 + String osName = System.getProperty("os.name"); + if (osName.contains("Windows")) { + sourceLocation = windowSourceLocation; + classConfigPath = windowsClassConfigPath; + } else if (osName.contains("Linux")) { + sourceLocation = linuxSourceLocation; + classConfigPath = linuxClassConfigPath; + } else { + throw new RuntimeException("暂无该系统"); + } + return new EngineConfig(); + } + +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/controller/RuleInfoController.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/controller/RuleInfoController.java new file mode 100644 index 0000000..8436473 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/controller/RuleInfoController.java @@ -0,0 +1,125 @@ +package com.muyu.etl.rule.controller; + +import com.muyu.common.core.domain.Result; +import com.muyu.common.core.utils.poi.ExcelUtil; +import com.muyu.common.core.web.controller.BaseController; +import com.muyu.common.core.web.page.TableDataInfo; +import com.muyu.common.security.annotation.RequiresPermissions; +import com.muyu.common.security.utils.SecurityUtils; +import com.muyu.etl.rule.domain.RuleInfo; +import com.muyu.etl.rule.domain.req.EtlRuleListReq; +import com.muyu.etl.rule.domain.resp.EtlRuleListResp; +import com.muyu.etl.rule.service.IRuleInfoService; +import com.muyu.etl.rule.service.IRuleVersionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.log4j.Log4j2; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; + +/** + * @Author WangXin + * @Data ${date} + * @Description 规则维护控制层 + * @Version 1.0.0 + */ +@RestController +@RequestMapping("/ruleInfo") +@Tag(name = "规则维护", description = "规则维护控制层") +@Log4j2 +public class RuleInfoController extends BaseController { + @Resource + private IRuleInfoService ruleInfoService; + @Resource + private IRuleVersionService ruleVersionService; + + /** + * 查询规则维护列表 + */ + @RequiresPermissions("engine:ruleInfo:list") + @PostMapping("/list") + @Operation(summary = "查询规则维护列表", description = "根据规则维护请求参数查询规则维护列表") + public Result> list(@RequestBody EtlRuleListReq ruleInfoReq) { + startPage(); + List list = ruleInfoService.selectRuleInfoList(ruleInfoReq); + log.info("数据总条数---》{}条", list.size()); + return getDataTable( + list.stream() + .map(ruleInfo -> EtlRuleListResp.buildEtlRuleListResp( + ruleInfo, ruleVersionService.selectRuleVersionListByRuleId(ruleInfo.getId()) + )) + .toList() + ); + } + + /** + * 导出规则维护列表 + */ + @RequiresPermissions("engine:ruleInfo:export") + @PostMapping("/export") + @Operation(summary = "导出规则维护列表", description = "根据规则维护请求参数导出规则维护列表") + public void export(HttpServletResponse response, @RequestBody EtlRuleListReq ruleInfoReq) { + List list = ruleInfoService.selectRuleInfoList(ruleInfoReq); + ExcelUtil util = new ExcelUtil(RuleInfo.class); + util.exportExcel(response, list, "规则维护数据"); + } + + /** + * 获取规则维护详细信息 + */ + @RequiresPermissions("engine:ruleInfo:query") + @GetMapping(value = "/{id}") + @Operation(summary = "获取规则维护详细信息", description = "根据规则维护id获取规则维护详细信息") + public Result getInfo(@PathVariable("id") Long id) { + return success(EtlRuleListResp.buildEtlRuleListResp( + ruleInfoService.selectRuleInfoById(id), + ruleVersionService.selectRuleVersionListByRuleId(id) + )); + } + + /** + * 新增规则维护 + */ + @RequiresPermissions("engine:ruleInfo:add") + @PostMapping + @Operation(summary = "新增规则维护", description = "根据规则维护请求参数新增规则维护") + public Result add( + @Validated @RequestBody RuleInfo ruleInfo) { + if (ruleInfoService.checkIdUnique(ruleInfo)) { + return error("新增 规则维护 '" + ruleInfo + "'失败,规则维护已存在"); + } + ruleInfo.setCreateBy(SecurityUtils.getUsername()); + return toAjax(ruleInfoService.save(ruleInfo)); + } + + /** + * 修改规则维护 + */ + @RequiresPermissions("engine:ruleInfo:edit") + @PutMapping + @Operation(summary = "修改规则维护", description = "根据规则维护Id修改规则维护") + public Result edit( + @Validated @RequestBody RuleInfo ruleInfo) { + if (!ruleInfoService.checkIdUnique(ruleInfo)) { + return error("修改 规则维护 '" + ruleInfo + "'失败,规则维护不存在"); + } + ruleInfo.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(ruleInfoService.updateById(ruleInfo)); + } + + /** + * 删除规则维护 + */ + @RequiresPermissions("engine:ruleInfo:remove") + @DeleteMapping("/{ids}") + @Operation(summary = "删除规则维护", description = "根据规则维护Id删除规则维护") + public Result remove(@PathVariable("ids") Long[] ids) { + ruleInfoService.removeBatchByIds(Arrays.asList(ids)); + return success(); + } +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/controller/RuleVersionController.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/controller/RuleVersionController.java new file mode 100644 index 0000000..09c0afe --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/controller/RuleVersionController.java @@ -0,0 +1,266 @@ +package com.muyu.etl.rule.controller; + +import java.util.Arrays; +import java.util.List; + +import com.dtflys.forest.annotation.Post; +import com.muyu.etl.data.access.domain.DataAnalysis; +import com.muyu.etl.data.access.domain.resp.TableInfoResp; +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.domain.RuleInfo; +import com.muyu.etl.rule.domain.req.DataTestReq; +import com.muyu.etl.rule.domain.req.ExecutionRuleVersionReq; +import com.muyu.etl.rule.domain.req.WriteFileReq; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; + +import javax.annotation.Resource; + +import org.apache.commons.codec.language.bm.RuleType; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import com.muyu.common.security.annotation.RequiresPermissions; +import com.muyu.etl.rule.domain.RuleVersion; +import com.muyu.etl.rule.service.IRuleVersionService; +import com.muyu.common.core.web.controller.BaseController; +import com.muyu.common.core.domain.Result; +import com.muyu.common.core.utils.poi.ExcelUtil; +import com.muyu.common.security.utils.SecurityUtils; +import org.springframework.validation.annotation.Validated; +import com.muyu.common.core.web.page.TableDataInfo; + +/** + * @Author wangXin + * @Data ${date} + * @Description 规则版本控制层 + * @Version 1.0.0 + */ +@RestController +@RequestMapping("/ruleVersion") +@Tag(name = "规则版本", description = "规则版本控制层") +public class RuleVersionController extends BaseController { + @Resource + private IRuleVersionService ruleVersionService; + + + /** + * 查询规则版本列表 + */ + @RequiresPermissions("engine:ruleVersion:list") + @PostMapping("/list") + @Operation(summary = "查询规则版本列表", description = "根据规则版本请求参数查询规则版本列表") + public Result> list(@RequestBody RuleVersion ruleVersion) { + startPage(); + List list = ruleVersionService.selectRuleVersionList(ruleVersion); + return getDataTable(list); + } + + /** + * 导出规则版本列表 + */ + @RequiresPermissions("engine:ruleVersion:export") + @PostMapping("/export") + @Operation(summary = "导出规则版本列表", description = "根据规则版本请求参数导出规则版本列表") + public void export(HttpServletResponse response, @RequestBody RuleVersion ruleVersion) { + List list = ruleVersionService.selectRuleVersionList(ruleVersion); + ExcelUtil util = new ExcelUtil(RuleVersion.class); + util.exportExcel(response, list, "规则版本数据"); + } + + /** + * 获取规则版本详细信息 + */ + @RequiresPermissions("engine:ruleVersion:query") + @GetMapping(value = "/{id}") + @Operation(summary = "获取规则版本详细信息", description = "根据规则版本id获取规则版本详细信息") + public Result> getInfo(@PathVariable("id") Long id) { + return success(ruleVersionService.selectRuleVersionById(id)); + } + + /** + * 新增规则版本 + */ + @RequiresPermissions("engine:ruleVersion:add") + @PostMapping + @Operation(summary = "新增规则版本", description = "根据规则版本请求参数新增规则版本") + @Transactional(rollbackFor = Exception.class) + public Result add( + @Validated @RequestBody RuleVersion ruleVersion) { + if (ruleVersionService.checkIdUnique(ruleVersion)) { + return error("新增 规则版本 '" + ruleVersion + "'失败,规则版本已存在"); + } + ruleVersion.setCreateBy(SecurityUtils.getUsername()); + boolean save = ruleVersionService.save(ruleVersion); + if (save) { + this.writeFile( + WriteFileReq.builder() + .fileName(ruleVersion.getRuleVersionClass()) + .content(ruleVersion.getClassContent()) + .build() + ); + } + return toAjax(save); + } + + /** + * 修改规则版本 + */ + @RequiresPermissions("engine:ruleVersion:edit") + @PutMapping + @Operation(summary = "修改规则版本", description = "根据规则版本Id修改规则版本") + public Result edit( + @Validated @RequestBody RuleVersion ruleVersion) { + if (!ruleVersionService.checkIdUnique(ruleVersion)) { + return error("修改 规则版本 '" + ruleVersion + "'失败,规则版本不存在"); + } + ruleVersion.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(ruleVersionService.updateById(ruleVersion)); + } + + /** + * 删除规则版本 + */ + @RequiresPermissions("engine:ruleVersion:remove") + @DeleteMapping("/{ids}") + @Operation(summary = "删除规则版本", description = "根据规则版本Id删除规则版本") + public Result remove(@PathVariable("ids") Long[] ids) { + ruleVersionService.removeBatchByIds(Arrays.asList(ids)); + return success(); + } + + /** + * 根据文件名称获取规则文件内容 + * + * @param fileName 文件名称 + * @return 文件内容 + */ + @RequiresPermissions("engine:ruleVersion:readFile") + @PostMapping("/readFile/{fileName}") + @Operation(summary = "根据文件名称读取文件内容", description = "根据文件名称读取文件内容") + public Result readFile(@PathVariable("fileName") String fileName) { + return Result.success(ruleVersionService.readFile(fileName)); + } + + /** + * 根据文件名称写规则文件内容 + * + * @param writeFileReq 文件写入请求对象 + * @return 结果集 + */ + @RequiresPermissions("engine:ruleVersion:writeFile") + @PostMapping("/writeFile") + @Operation(summary = "根据文件名称写入文件内容", description = "根据文件名称写入文件内容") + public Result writeFile(@RequestBody WriteFileReq writeFileReq) { + ruleVersionService.writeFile(writeFileReq); + return Result.success(); + } + + /** + * 执行java文件 + */ + @RequiresPermissions("engine:ruleVersion:execution") + @PostMapping("/execution") + @Operation(summary = "执行java文件", description = "执行java文件") + public Result executionRuleVersion(@RequestBody ExecutionRuleVersionReq executionRuleVersionReq) { + return Result.success(ruleVersionService.executionRuleVersion(executionRuleVersionReq)); + } + + /** + * 执行值java文件 + */ + @RequiresPermissions("engine:ruleVersion:execution") + @PostMapping("/execution/{engineKey}") + @Operation(summary = "执行值java文件", description = "执行值java文件") + public Result executionRuleVersion(@PathVariable("engineKey") String engineKey, @RequestBody DataStructure dataStructure) { + return Result.success(ruleVersionService.executionRuleValueVersion(engineKey, dataStructure)); + } + + + /** + * 执行行java文件 + */ + @RequiresPermissions("engine:ruleVersion:execution") + @PostMapping("/lineFile/{engineKey}") + @Operation(summary = "执行行java文件", description = "执行行java文件") + public Result executionLineRuleVersion(@PathVariable("engineKey") String engineKey, @RequestBody DataStructure[][] dataStructureRow) { + + return Result.success(ruleVersionService.executionRowRuleVersion(engineKey, dataStructureRow)); + } + + /** + * 执行组java文件 + */ + @RequiresPermissions("engine:ruleVersion:execution") + @PostMapping("/groupFile/{engineKey}") + @Operation(summary = "执行组java文件", description = "执行组java文件") + public Result executionGroupRuleVersion(@PathVariable("engineKey") String engineKey, @RequestBody DataStructure[][] dataStructureRows) { + return Result.success(ruleVersionService.executionRowsRuleVersion(engineKey, dataStructureRows)); + } + + /** + * 库表远调二级联动 + * @return 库表的二级联动 + */ + @GetMapping("/dataSource/tableInfo") + @Operation(summary = "库表远调二级联动", description = "数据接入课表接入的二级联动,方便数据的选择") + public Result> dataSourceList() { + return Result.success(ruleVersionService.dataSourceList()); + } + + /** + * 获取表结构 + * @param id 表id + * @return 数据表结构 + */ + @GetMapping("/dataSource/table/{id}") + public Result> dataSource(@PathVariable("id") Long id) { + return Result.success(ruleVersionService.dataFindById(id)); + } + + /** + * 获取表数据 + * @param dataTestReq 数据测试请求对象 + * @return ktlv数据结构 + */ + @PostMapping("/getEtlTableData") + public Result>> getEtlTableData(@RequestBody DataTestReq dataTestReq) { + return Result.success(ruleVersionService.testData(dataTestReq)); + } + + @GetMapping("/isClassExist/{className}") + public Result isClassExist(@PathVariable("className") String className) { + return Result.success(ruleVersionService.isClassExist(className)); + } + + /** + * 查詢所有規則(字段,数据集,记录)规则下拉框 + * @return List + */ + @GetMapping("/getEtlRuleAll") + public Result> getEtlRuleTypeByRuleId() { + return Result.success(ruleVersionService.getEtlRuleTypeByRuleId()); + } + + /** + * 根据规则id查询子规则类型 + * @param id + * @return List + */ + @GetMapping("/getEtlRuleTypeVById") + public Result> getEtlRuleTypeVById(@RequestParam("id") Long id) { + return Result.success(ruleVersionService.getEtlRuleTypeVById(id)); + } + + /** + * 根据版本类型id查询 返回版本类型对象 + * @param id + * @return RuleVersion + */ + @GetMapping("/getETlRuleTypeVersionById") + public Result getETlRuleTypeVersionById(@RequestParam("id") Long id) { + return Result.success( ruleVersionService.getById(id)); + } + + +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/mapper/RuleInfoMapper.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/mapper/RuleInfoMapper.java new file mode 100644 index 0000000..0ac41c9 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/mapper/RuleInfoMapper.java @@ -0,0 +1,19 @@ +package com.muyu.etl.rule.mapper; + +import java.util.List; +import com.muyu.etl.rule.domain.RuleInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.muyu.etl.rule.domain.req.EtlRuleListReq; +import org.apache.ibatis.annotations.Mapper; + +/** + * 规则维护Mapper接口 + * + * @author WangXin + * @date 2024-08-25 + */ +@Mapper +public interface RuleInfoMapper extends BaseMapper{ + + List selectRuleInfoList(EtlRuleListReq ruleInfoReq); +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/mapper/RuleVersionMapper.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/mapper/RuleVersionMapper.java new file mode 100644 index 0000000..11709d2 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/mapper/RuleVersionMapper.java @@ -0,0 +1,17 @@ +package com.muyu.etl.rule.mapper; + +import java.util.List; +import com.muyu.etl.rule.domain.RuleVersion; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 规则版本Mapper接口 + * + * @author wangXin + * @date 2024-08-25 + */ +@Mapper +public interface RuleVersionMapper extends BaseMapper{ + +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/operation/ArrayUtil.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/operation/ArrayUtil.java new file mode 100644 index 0000000..ab0979a --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/operation/ArrayUtil.java @@ -0,0 +1,89 @@ +package com.muyu.etl.rule.operation; + +import com.alibaba.fastjson2.JSONObject; +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.enums.DataType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.extern.log4j.Log4j2; + +import java.util.Arrays; +import java.util.Iterator; + +/** + * @Author WangXin + * @Data 2024/9/3 + * @Description 压栈工具 + * @Version 1.0.0 + */ +@Data +@Builder +@AllArgsConstructor +@Log4j2 +public class ArrayUtil implements Iterator { + + private final T[] originalArray; // 原始数组 + private T[] currentArray; // 当前数组,用于迭代 + private int currentIndex; // 当前索引 + private int lastReturnedIndex; // 上一次调用next()方法时返回的索引 + private boolean canRemove = false; // 标记是否可以移除元素 + + public ArrayUtil(T[] array) { + this.originalArray = array; + this.currentArray = Arrays.copyOf(array, array.length); + this.currentIndex = 0; + } + + @Override + public boolean hasNext() { + return currentIndex < currentArray.length; + } + + @Override + public T next() { + if (!hasNext()) { + throw new IllegalStateException("No more elements"); + } + lastReturnedIndex = currentIndex; + canRemove = true; // 调用next()后可以调用remove() + return currentArray[currentIndex++]; + } + + @Override + public void remove() { + if (!canRemove) { + throw new IllegalStateException("Cannot call remove() without calling next()"); + } + // 删除元素并更新数组 + System.arraycopy(currentArray, lastReturnedIndex + 1, currentArray, lastReturnedIndex, currentArray.length - lastReturnedIndex - 1); + currentArray = Arrays.copyOf(currentArray, currentArray.length - 1); // 缩小数组大小 + currentIndex--; // 因为我们移除了当前元素,所以索引应该减一 + canRemove = false; + } + + + + public static void main(String[] args) { + DataStructure[] dataStructures = new DataStructure[6]; + dataStructures[0] = DataStructure.builder().value("aaa1").key("name").type(DataType.STRING).label("姓名").build(); + dataStructures[1] = DataStructure.builder().value("aaa2").key("name").type(DataType.STRING).label("姓名").build(); + dataStructures[2] = DataStructure.builder().value("aaa3").key("name").type(DataType.STRING).label("姓名").build(); + dataStructures[3] = DataStructure.builder().value("aaa4").key("name").type(DataType.STRING).label("姓名").build(); + dataStructures[4] = DataStructure.builder().value("aaa5").key("name").type(DataType.STRING).label("姓名").build(); + dataStructures[5] = DataStructure.builder().value("aaa6").key("name").type(DataType.STRING).label("姓名").build(); + + ArrayUtil dataStructureArrayUtil = new ArrayUtil<>(dataStructures); + log.info(dataStructureArrayUtil.originalArray.length); + log.info(JSONObject.toJSONString(dataStructureArrayUtil.originalArray)); + while (dataStructureArrayUtil.hasNext()){ + DataStructure next = dataStructureArrayUtil.next(); + if (next.getValue().equals("aaa3")){ + dataStructureArrayUtil.remove(); + } + } + log.info(dataStructureArrayUtil.currentArray.length); + log.info(Arrays.toString(dataStructureArrayUtil.currentArray)); + + } +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/service/IRuleInfoService.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/IRuleInfoService.java new file mode 100644 index 0000000..2003290 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/IRuleInfoService.java @@ -0,0 +1,37 @@ +package com.muyu.etl.rule.service; + +import java.util.List; +import com.muyu.etl.rule.domain.RuleInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.muyu.etl.rule.domain.req.EtlRuleListReq; + +/** + * 规则维护Service接口 + * + * @author WangXin + * @date 2024-08-25 + */ +public interface IRuleInfoService extends IService { + /** + * 精确查询规则维护 + * + * @param id 规则维护主键 + * @return 规则维护 + */ + public RuleInfo selectRuleInfoById(Long id); + + /** + * 查询规则维护列表 + * @param ruleInfoReq 规则维护 + * @return 规则维护集合 + */ + public List selectRuleInfoList(EtlRuleListReq ruleInfoReq); + + /** + * 判断 规则维护 id是否唯一 + * @param ruleInfo 规则维护 + * @return 结果 + */ + Boolean checkIdUnique(RuleInfo ruleInfo); + +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/service/IRuleVersionService.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/IRuleVersionService.java new file mode 100644 index 0000000..a046208 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/IRuleVersionService.java @@ -0,0 +1,131 @@ +package com.muyu.etl.rule.service; + +import java.util.List; + +import com.muyu.common.core.domain.Result; +import com.muyu.etl.data.access.domain.DataAnalysis; +import com.muyu.etl.data.access.domain.resp.TableInfoResp; +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.domain.RuleInfo; +import com.muyu.etl.rule.domain.RuleVersion; +import com.baomidou.mybatisplus.extension.service.IService; +import com.muyu.etl.rule.domain.req.DataTestReq; +import com.muyu.etl.rule.domain.req.ExecutionRuleVersionReq; +import com.muyu.etl.rule.domain.req.WriteFileReq; +import org.apache.commons.codec.language.bm.RuleType; + +/** + * 规则版本Service接口 + * + * @author wangXin + * @date 2024-08-25 + */ +public interface IRuleVersionService extends IService { + /** + * 精确查询规则版本 + * + * @param id 规则版本主键 + * @return 规则版本 + */ + public RuleVersion selectRuleVersionById(Long id); + + /** + * 查询规则版本列表 + * + * @param ruleVersion 规则版本 + * @return 规则版本集合 + */ + public List selectRuleVersionList(RuleVersion ruleVersion); + + /** + * 判断 规则版本 id是否唯一 + * @param ruleVersion 规则版本 + * @return 结果 + */ + Boolean checkIdUnique(RuleVersion ruleVersion); + + /** + * 通过规则id查询规则版本集合 + * @param id 规则id + * @return 规则版本数据集 + */ + List selectRuleVersionListByRuleId(Long id); + + /** + * 根据文件名称获取规则文件内容 + * @param fileName 文件名称 + * @return 文件内容 + */ + String readFile(String fileName); + /** + * 根据文件名称写入规则文件内容 + * @param writeFileReq 文件名称 + */ + void writeFile(WriteFileReq writeFileReq); + + /** + * 执行规则 + * @param executionRuleVersionReq 规则请求参数 + */ + Object executionRuleVersion(ExecutionRuleVersionReq executionRuleVersionReq); + + /** + * 执行值规则 + * @param engineKey 规则类名 + * @param dataStructure 规则值处理数据 + */ + DataStructure executionRuleValueVersion(String engineKey, DataStructure dataStructure); + + /** + * 执行值规则 + * @param engineKey 规则类名 + * @param dataStructureRow 规则行处理数据 + */ + DataStructure[][] executionRowRuleVersion(String engineKey, DataStructure[][] dataStructureRow); + + /** + * 执行值规则 + * @param engineKey 规则类名 + * @param dataStructureRows 规则组处理数据 + */ + DataStructure[][] executionRowsRuleVersion(String engineKey, DataStructure[][] dataStructureRows); + + + /** + * 数据源列表 + * @return + */ + List dataSourceList(); + + + /** + * 根据id查询数据表详情 + * @param id 表id + * @return 表结构 + */ + List dataFindById(Long id); + + /** + * 测试数据 + * @param dataTestReq 测试请求参数 + * @return 测试结果 + */ + List> testData(DataTestReq dataTestReq); + + /** + * + * @param className + * @return + */ + Boolean isClassExist(String className); + /** + * 查詢所有規則(字段,数据集,记录)规则下拉框 + * @return List + */ + List getEtlRuleTypeByRuleId(); + + + List getEtlRuleTypeVById(Long id); + + +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/service/impl/RuleInfoServiceImpl.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/impl/RuleInfoServiceImpl.java new file mode 100644 index 0000000..9b7b972 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/impl/RuleInfoServiceImpl.java @@ -0,0 +1,69 @@ +package com.muyu.etl.rule.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.muyu.etl.rule.domain.RuleInfo; +import com.muyu.etl.rule.domain.req.EtlRuleListReq; +import com.muyu.etl.rule.mapper.RuleInfoMapper; +import com.muyu.etl.rule.service.IRuleInfoService; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 规则维护Service业务层处理 + * + * @author WangXin + * @date 2024-08-25 + */ +@Service +public class RuleInfoServiceImpl + extends ServiceImpl + implements IRuleInfoService { + + @Resource + private RuleInfoMapper ruleInfoMapper; + + /** + * 精确查询规则维护 + * + * @param id 规则维护主键 + * @return 规则维护 + */ + @Override + public RuleInfo selectRuleInfoById(Long id) + { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + Assert.notNull(id, "id不可为空"); + queryWrapper.eq(RuleInfo::getId, id); + return this.getOne(queryWrapper); + } + + + /** + * 查询规则维护列表 + * + * @param ruleInfoReq 规则维护 + * @return 规则维护 + */ + @Override + public List selectRuleInfoList(EtlRuleListReq ruleInfoReq) + { + return ruleInfoMapper.selectRuleInfoList(ruleInfoReq); + } + + /** + * 唯一 判断 + * @param ruleInfo 规则维护 + * @return 规则维护 + */ + @Override + public Boolean checkIdUnique(RuleInfo ruleInfo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RuleInfo::getId, ruleInfo.getId()); + return this.count(queryWrapper) > 0; + } + +} diff --git a/etl-rule-server/src/main/java/com/muyu/etl/rule/service/impl/RuleVersionServiceImpl.java b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/impl/RuleVersionServiceImpl.java new file mode 100644 index 0000000..f1c61f4 --- /dev/null +++ b/etl-rule-server/src/main/java/com/muyu/etl/rule/service/impl/RuleVersionServiceImpl.java @@ -0,0 +1,383 @@ +package com.muyu.etl.rule.service.impl; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.muyu.common.core.utils.OssUtil; +import com.muyu.common.core.utils.StringUtils; +import com.muyu.common.core.utils.sign.Base64; +import com.muyu.etl.data.access.domain.DataAnalysis; +import com.muyu.etl.data.access.domain.req.EtlDataSqlReq; +import com.muyu.etl.data.access.domain.resp.TableInfoResp; +import com.muyu.etl.data.access.remote.RemoteDataAnalysisService; +import com.muyu.etl.data.access.remote.RemoteEtlDataService; +import com.muyu.etl.data.access.remote.RemoteTableInfoService; +import com.muyu.etl.domain.DataStructure; +import com.muyu.etl.rule.domain.RuleInfo; +import com.muyu.etl.rule.engine.bean.constant.FileConstants; +import com.muyu.etl.rule.engine.core.EngineContainer; +import com.muyu.etl.rule.engine.core.EngineExecution; +import com.muyu.etl.rule.engine.core.classLoad.JavaBinaryClassLoader; +import com.muyu.etl.rule.engine.core.complier.SourceCodeCompiler; +import com.muyu.etl.rule.engine.util.FileLoadUtil; +import com.muyu.etl.rule.basic.BasicEngine; +import com.muyu.etl.rule.config.EngineConfig; +import com.muyu.etl.rule.domain.RuleVersion; +import com.muyu.etl.rule.domain.req.DataSqlField; +import com.muyu.etl.rule.domain.req.DataTestReq; +import com.muyu.etl.rule.domain.req.ExecutionRuleVersionReq; +import com.muyu.etl.rule.domain.req.WriteFileReq; +import com.muyu.etl.rule.mapper.RuleVersionMapper; +import com.muyu.etl.rule.service.IRuleVersionService; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.codec.language.bm.RuleType; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import javax.annotation.Resource; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 规则版本Service业务层处理 + * + * @author wangXin + * @date 2024-08-25 + */ +@Service +@Log4j2 +public class RuleVersionServiceImpl + extends ServiceImpl + implements IRuleVersionService { + + @Resource + private EngineConfig engineConfig; + @Resource + private RemoteEtlDataService remoteEtlDataService; + @Resource + private RemoteTableInfoService remoteTableInfoService; + @Resource + private RemoteDataAnalysisService remoteDataAnalysisService; + + + /** + * 精确查询规则版本 + * + * @param id 规则版本主键 + * @return 规则版本 + */ + @Override + public RuleVersion selectRuleVersionById(Long id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + Assert.notNull(id, "id不可为空"); + queryWrapper.eq(RuleVersion::getId, id); + return this.getOne(queryWrapper); + } + + + /** + * 查询规则版本列表 + * + * @param ruleVersion 规则版本 + * @return 规则版本 + */ + @Override + public List selectRuleVersionList(RuleVersion ruleVersion) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(ruleVersion.getRuleVersionName())) { + queryWrapper.like(RuleVersion::getRuleVersionName, ruleVersion.getRuleVersionName()); + } + if (StringUtils.isNotEmpty(ruleVersion.getRuleVersionCode())) { + queryWrapper.eq(RuleVersion::getRuleVersionCode, ruleVersion.getRuleVersionCode()); + } + if (ruleVersion.getRuleVersionIsActivation() != null) { + queryWrapper.eq(RuleVersion::getRuleVersionIsActivation, ruleVersion.getRuleVersionIsActivation()); + } + if (ruleVersion.getRuleVersionIsTest() != null) { + queryWrapper.eq(RuleVersion::getRuleVersionIsTest, ruleVersion.getRuleVersionIsTest()); + } + if (ruleVersion.getRuleVersionStatus() != null) { + queryWrapper.eq(RuleVersion::getRuleVersionStatus, ruleVersion.getRuleVersionStatus()); + } + return this.list(queryWrapper); + } + + /** + * 唯一 判断 + * + * @param ruleVersion 规则版本 + * @return 规则版本 + */ + @Override + public Boolean checkIdUnique(RuleVersion ruleVersion) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RuleVersion::getId, ruleVersion.getId()); + return this.count(queryWrapper) > 0; + } + + /** + * 通过规则id查询规则版本 + * + * @param id 规则Id + * @return 规则版本数据集合 + */ + @Override + public List selectRuleVersionListByRuleId(Long id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RuleVersion::getRuleId, id); + return this.list(queryWrapper).stream() + .peek(ruleVersion -> ruleVersion.setClassContent(readFile(ruleVersion.getRuleVersionClass()))) + .collect(Collectors.toList()); + } + + /** + * 根据文件名称获取规则文件内容 + * + * @param fileName 文件名称 + * @return 文件内容 + */ + @Override + public String readFile(String fileName) { + log.info("readFile请求入参:[fileName:{}]", fileName); + return FileLoadUtil.readFile(engineConfig.getSourceLocation(), fileName); + } + + /** + * 根据文件名称写规则文件内容 + * + * @param writeFileReq 文件写入请求对象 + */ + @Override + public void writeFile(WriteFileReq writeFileReq) { + String content = new String(Base64.decode(writeFileReq.getContent())); + FileLoadUtil.writeFile(engineConfig.getSourceLocation(), writeFileReq.getFileName(), content); + OssUtil.uploadFile(engineConfig.getSourceLocation() + FileConstants.FILE_DELIMITER + writeFileReq.getFileName().split("_")[0] + FileConstants.FILE_DELIMITER + writeFileReq.getFileName() + FileConstants.JAVA_SUFFIX); + } + + /** + * 执行规则 + * + * @param executionRuleVersionReq 规则请求参数 + */ + @Override + public Object executionRuleVersion(ExecutionRuleVersionReq executionRuleVersionReq) { + return executionRule(executionRuleVersionReq); + } + + /** + * 执行值规则 + * + * @param engineKey 规则类名 + * @param dataStructure 规则值处理数据 + */ + @Override + public DataStructure executionRuleValueVersion(String engineKey, DataStructure dataStructure) { + return executionValueRule(engineKey, dataStructure); + } + + /** + * 执行值规则 + * + * @param engineKey 规则类名 + * @param dataStructureRow 规则行处理数据 + */ + @Override + public DataStructure[][] executionRowRuleVersion(String engineKey, DataStructure[][] dataStructureRow) { + ArrayList dataStructures = new ArrayList<>(); + for (DataStructure[] dataStructure : dataStructureRow) { + DataStructure[] dataStructure1 = executionValueRule(engineKey, dataStructure); + if (dataStructure1 != null && dataStructure1.length > 0) { + dataStructures.add(dataStructure1); + } + } + return dataStructures.toArray(new DataStructure[dataStructures.size()][]); + } + + /** + * 执行值规则 + * + * @param engineKey 规则类名 + * @param dataStructureRows 规则组处理数据 + */ + @Override + public DataStructure[][] executionRowsRuleVersion(String engineKey, DataStructure[][] dataStructureRows) { + return executionValueRule(engineKey, dataStructureRows); + } + + /** + * 远调查询数据源 + * + * @return 数据库表二级联动 + */ + @Override + public List dataSourceList() { + return remoteTableInfoService.findByTableName().getData(); + } + + @Override + public List dataFindById(Long id) { + return remoteDataAnalysisService.findDataAnalysisByTableId(id).getData(); + } + + @Override + public List> testData(DataTestReq dataTestReq) { + return remoteEtlDataService.selEtlData(EtlDataSqlReq.builder() + .sql(spliceSql(dataTestReq)) + .basicId(dataTestReq.getBasicId()) + .build()).getData(); + } + + @Override + public Boolean isClassExist(String className) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RuleVersion::getRuleVersionClass, className); + return this.exists(queryWrapper); + } + + + + /** + * 凭借sql + * + * @param dataTestReq + * @return + */ + private String spliceSql(DataTestReq dataTestReq) { + List list = dataTestReq.getRows().stream().map(DataSqlField::getColumnName).collect(Collectors.toList()); + String sql = "SELECT " + list.stream().collect(Collectors.joining(",")) + " FROM " + dataTestReq.getTableName(); + log.info("拼接SQL语句为 --->[{}]", sql); + return sql; + } + + /** + * 执行有参数的规则方法 + * + * @param executionRuleVersionReq 规则请求参数 + * @return 返回结果集 + */ + private Object executionRule(ExecutionRuleVersionReq executionRuleVersionReq) { + //将java文件编译成class文件 + SourceCodeCompiler.javaCompilerPath(engineConfig.getSourceLocation()); + //获取所有class文件的class对象 + Map> stringClassMap = JavaBinaryClassLoader + .loadClassByLocation(engineConfig.getPackageName(), + engineConfig.sourceLocation); + + //实将所有class对象进行例化,并进行存储 + stringClassMap.forEach((k, v) -> { + EngineContainer.loadEngineInstance(engineConfig.methodName, k, v); + }); + return EngineExecution.argumentEngineExe(executionRuleVersionReq.getEngineKey(), executionRuleVersionReq.getParams()); + } + + /** + * 将单文件编译为class文件 + */ + private String javaCompile(String fileName) { + //将java文件编译成class文件 + SourceCodeCompiler.javaCompiler("", new File(getFilePath(fileName, FileConstants.JAVA_SUFFIX))); + //返回oss中class文件地址 + return OssUtil.uploadFile(getFilePath(fileName, FileConstants.CLASS_SUFFIX)); + } + + /** + * 将文件名转为特定文件地址 + * + * @param fileName 文件名 + * @param endWih 文件后缀 + * @return 文件地址 + */ + private String getFilePath(String fileName, String endWih) { + return engineConfig.getSourceLocation() + FileConstants.FILE_DELIMITER + fileName.split("_")[0] + FileConstants.FILE_DELIMITER + fileName + endWih; + } + + + /** + * 执行无参的规则方法 + * + * @param engineKey 规则类名 + */ + private T executionValueRule(String engineKey, T t) { + log.info("配置参数为 ------》 SourceLocation:{} | PackageName:{}", engineConfig.getSourceLocation(), engineConfig.getPackageName()); + log.info("请求类-----》 {}", engineKey); + log.info("请求参数为----》{}", JSONObject.toJSONString(t)); + String path = engineConfig.getSourceLocation() + FileConstants.FILE_DELIMITER + engineKey.split("_")[0]; + //将java文件编译成class文件 + SourceCodeCompiler.javaCompiler(engineConfig.classConfigPath, path + "/classes", path, engineKey); + //获取所有class文件的class对象 + Map> stringClassMap = JavaBinaryClassLoader + .loadClassByLocation(engineConfig.getPackageName(), + path+ "/classes"); + log.info("[{}] 类编译成功 ", engineKey); + //实将所有class对象进行例化,并进行存储 + stringClassMap.forEach((k, v) -> { + EngineContainer.loadEngineInstance(engineConfig.methodName, k, v); + }); + log.info("[{}] 类实例化成功", engineKey); + ConcurrentHashMap instanceMap = EngineContainer.instanceMap; + Object object = instanceMap.get(engineKey); + log.info("返回值对象:object:{}", object); + if (object != null && object instanceof BasicEngine) { + BasicEngine engine = (BasicEngine) object; + engine.set(t); + engine.execution(); + log.info("[{}]类加载成功", engineKey); + T engineData = engine.get(); + log.info("[{}]处理数据结果为[{}]", engineKey, JSONObject.toJSONString(engineData)); + return engineData; + } else { + throw new RuntimeException("对象类型错误"); + } + } + + + public static void main(String[] args) { + +// String engineKey = "TelTuoMing"; +// String locationPath = "C:\\Users\\wx\\Desktop\\测试"; +// String page = "com.muyu.etl.rule"; +// +// SourceCodeCompiler.javaCompilerPath(locationPath); +// +// Map> stringClassMap = JavaBinaryClassLoader +// .loadClassByLocation(page, locationPath); +// +// stringClassMap.forEach((k, v) -> { +// EngineContainer.loadEngineInstance("run", k, v); +// }); +// +// DataStructure dataStructure = new DataStructure(); +// dataStructure.setValue("15335893491"); +// dataStructure.setType(DataType.STRING); +// dataStructure.setKey("tel"); +// dataStructure.setLabel("手机号"); +// +// ConcurrentHashMap instanceMap = EngineContainer.instanceMap; +// Object object = instanceMap.get(engineKey); +// if (object != null && object instanceof BasicEngine) { +// BasicEngine engine = (BasicEngine) object; +// engine.set(dataStructure); +// engine.execution(); +// } + + } + /** + * 查詢所有規則(字段,数据集,记录)规则下拉框 + * @return List + */ + @Override + public List getEtlRuleTypeByRuleId() { + return List.of(); + } + + @Override + public List getEtlRuleTypeVById(Long id) { + return List.of(); + } + + +} diff --git a/etl-rule-server/src/main/resources/banner.txt b/etl-rule-server/src/main/resources/banner.txt new file mode 100644 index 0000000..0dd5eee --- /dev/null +++ b/etl-rule-server/src/main/resources/banner.txt @@ -0,0 +1,2 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} diff --git a/etl-rule-server/src/main/resources/bootstrap.yml b/etl-rule-server/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..9a6dd76 --- /dev/null +++ b/etl-rule-server/src/main/resources/bootstrap.yml @@ -0,0 +1,56 @@ +# Tomcat +server: + port: 10003 + +# nacos线上地址 +nacos: + addr: 10.0.1.97:8848 + user-name: nacos + password: nacos + namespace: wu_zu_cloud + +# Spring +spring: + main: + allow-bean-definition-overriding: true + application: + # 应用名称 + name: cloud-rule-engine + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: ${nacos.addr} + # nacos用户名 + username: ${nacos.user-name} + # nacos密码 + password: ${nacos.password} + # 命名空间 + namespace: ${nacos.namespace} + config: + # 服务注册地址 + server-addr: ${nacos.addr} + # nacos用户名 + username: ${nacos.user-name} + # nacos密码 + password: ${nacos.password} + # 命名空间 + namespace: ${nacos.namespace} + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + # 系统共享配置 + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + # 系统环境Config共享配置 + - application-config-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + # xxl-job 配置文件 + - application-xxl-config-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + # engine配置 + - engine-config-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} +logging: + level: + com.muyu.system.mapper: DEBUG diff --git a/etl-rule-server/src/main/resources/logback/dev.xml b/etl-rule-server/src/main/resources/logback/dev.xml new file mode 100644 index 0000000..13510e7 --- /dev/null +++ b/etl-rule-server/src/main/resources/logback/dev.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + diff --git a/etl-rule-server/src/main/resources/logback/prod.xml b/etl-rule-server/src/main/resources/logback/prod.xml new file mode 100644 index 0000000..878147c --- /dev/null +++ b/etl-rule-server/src/main/resources/logback/prod.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + ${log.sky.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + + + ERROR + + ACCEPT + + DENY + + + + + + + + ${log.sky.pattern} + + + + + + + + + + + + + + + + + + + + diff --git a/etl-rule-server/src/main/resources/logback/test.xml b/etl-rule-server/src/main/resources/logback/test.xml new file mode 100644 index 0000000..878147c --- /dev/null +++ b/etl-rule-server/src/main/resources/logback/test.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + ${log.sky.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + + + ERROR + + ACCEPT + + DENY + + + + + + + + ${log.sky.pattern} + + + + + + + + + + + + + + + + + + + + diff --git a/etl-rule-server/src/main/resources/mapper/RuleInfoMapper.xml b/etl-rule-server/src/main/resources/mapper/RuleInfoMapper.xml new file mode 100644 index 0000000..6d5d232 --- /dev/null +++ b/etl-rule-server/src/main/resources/mapper/RuleInfoMapper.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + select id, rule_name, rule_code, rule_type_value, rule_level_id, is_activation, status, rule_explain, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, remark, CREATE_BY_NAME, UPDATE_BY_NAME from etl_rule_info + + + + + + + + insert into etl_rule_info + + rule_name, + rule_code, + rule_type_value, + rule_level_id, + is_activation, + status, + rule_explain, + CREATE_BY, + CREATE_TIME, + UPDATE_BY, + UPDATE_TIME, + remark, + CREATE_BY_NAME, + UPDATE_BY_NAME, + + + #{ruleName}, + #{ruleCode}, + #{ruleTypeValue}, + #{ruleLevelId}, + #{isActivation}, + #{status}, + #{ruleExplain}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{remark}, + #{createByName}, + #{updateByName}, + + + + + update etl_rule_info + + rule_name = #{ruleName}, + rule_code = #{ruleCode}, + rule_type_value = #{ruleTypeValue}, + rule_level_id = #{ruleLevelId}, + is_activation = #{isActivation}, + status = #{status}, + rule_explain = #{ruleExplain}, + CREATE_BY = #{createBy}, + CREATE_TIME = #{createTime}, + UPDATE_BY = #{updateBy}, + UPDATE_TIME = #{updateTime}, + remark = #{remark}, + CREATE_BY_NAME = #{createByName}, + UPDATE_BY_NAME = #{updateByName}, + + where id = #{id} + + + + delete from etl_rule_info where id = #{id} + + + + delete from etl_rule_info where id in + + #{id} + + + diff --git a/etl-rule-server/src/main/resources/mapper/RuleVersionMapper.xml b/etl-rule-server/src/main/resources/mapper/RuleVersionMapper.xml new file mode 100644 index 0000000..7d96fdf --- /dev/null +++ b/etl-rule-server/src/main/resources/mapper/RuleVersionMapper.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + select id, rule_version_class, rule_version_name, rule_version_code, rule_version_is_activation, rule_version_is_test, rule_version_status, rule_version_described, rule_id, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, remark, CREATE_BY_NAME, UPDATE_BY_NAME from etl_rule_version + + + + + + + + insert into etl_rule_version + + rule_version_class, + rule_version_name, + rule_version_code, + rule_version_is_activation, + rule_version_is_test, + rule_version_status, + rule_version_described, + rule_id, + CREATE_BY, + CREATE_TIME, + UPDATE_BY, + UPDATE_TIME, + remark, + CREATE_BY_NAME, + UPDATE_BY_NAME, + + + #{ruleVersionClass}, + #{ruleVersionName}, + #{ruleVersionCode}, + #{ruleVersionIsActivation}, + #{ruleVersionIsTest}, + #{ruleVersionStatus}, + #{ruleVersionDescribed}, + #{ruleId}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{remark}, + #{createByName}, + #{updateByName}, + + + + + update etl_rule_version + + rule_version_class = #{ruleVersionClass}, + rule_version_name = #{ruleVersionName}, + rule_version_code = #{ruleVersionCode}, + rule_version_is_activation = #{ruleVersionIsActivation}, + rule_version_is_test = #{ruleVersionIsTest}, + rule_version_status = #{ruleVersionStatus}, + rule_version_described = #{ruleVersionDescribed}, + rule_id = #{ruleId}, + CREATE_BY = #{createBy}, + CREATE_TIME = #{createTime}, + UPDATE_BY = #{updateBy}, + UPDATE_TIME = #{updateTime}, + remark = #{remark}, + CREATE_BY_NAME = #{createByName}, + UPDATE_BY_NAME = #{updateByName}, + + where id = #{id} + + + + delete from etl_rule_version where id = #{id} + + + + delete from etl_rule_version where id in + + #{id} + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8e95dd2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + com.muyu + cloud-modules + 3.6.5 + + + cloud-rule-engine + 3.6.5 + pom + + etl-rule-common + etl-rule-remote + etl-rule-server + + + + 17 + 17 + UTF-8 + + + + + yun-releases + yun-releases + http://10.0.1.3:8081/repository/maven-releases/ + + +