初始化
commit
40fdd3147c
|
@ -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
|
|
@ -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"]
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-rule-engine</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>etl-rule-common</artifactId>
|
||||
<version>3.6.5</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-etl-common</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-common-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -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<V> {
|
||||
|
||||
public void set(V value);
|
||||
|
||||
public V get();
|
||||
|
||||
public default void remove() {
|
||||
BasicEngineHandler.remove();
|
||||
}
|
||||
|
||||
public void execution();
|
||||
}
|
|
@ -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<DataStructure[]> {
|
||||
|
||||
@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();
|
||||
}
|
|
@ -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<DataStructure[][]> {
|
||||
@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();
|
||||
}
|
|
@ -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<DataStructure> {
|
||||
|
||||
|
||||
@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();
|
||||
}
|
|
@ -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<Object> threadLocal = new ThreadLocal<>();
|
||||
|
||||
public static void set(final Object handler) {
|
||||
threadLocal.set(handler);
|
||||
}
|
||||
|
||||
public static <T> T get() {
|
||||
return (T) threadLocal.get();
|
||||
}
|
||||
|
||||
public static void remove() {
|
||||
|
||||
}
|
||||
}
|
|
@ -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<DataStructure[]> threadLocal = new ThreadLocal<>();
|
||||
|
||||
public static void set(DataStructure[] dataStructureRow){
|
||||
threadLocal.set(dataStructureRow);
|
||||
}
|
||||
|
||||
public static DataStructure[] get(){
|
||||
return threadLocal.get();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<DataStructure[][]> threadLocal = new ThreadLocal<>();
|
||||
|
||||
public static void set(DataStructure[][] dataStructureRows){
|
||||
threadLocal.set(dataStructureRows);
|
||||
}
|
||||
|
||||
public static DataStructure[][] get(){
|
||||
return threadLocal.get();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.muyu.etl.rule.domain;
|
||||
|
||||
/**
|
||||
* @Author WangXin
|
||||
* @Data 2024/9/1
|
||||
* @Description 参数类型
|
||||
* @Version 1.0.0
|
||||
*/
|
||||
public class DataStructureResp {
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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<DataSqlField> rows;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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<String, Object> params;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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<RuleVersion> ruleVersionList;
|
||||
|
||||
public static EtlRuleListResp buildEtlRuleListResp(RuleInfo ruleInfo, List<RuleVersion> 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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 "";
|
||||
}
|
|
@ -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") ? "\\" : "/";
|
||||
}
|
|
@ -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<String, Object> instanceMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
private final static ConcurrentHashMap<String, Class<?>> classMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
private final static ConcurrentHashMap<String, Method> methodMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
private final static ConcurrentHashMap<String, List<String>> methodEngineParamMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
public static void loadEngineInstance(String methodName, String engineKey, Class<?> aClass) {
|
||||
|
||||
Method method = findByMethodByClass(methodName, aClass);
|
||||
|
||||
List<String> 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<String> getMethodEngineParam(String engineKey) {
|
||||
return methodEngineParamMap.get(engineKey);
|
||||
}
|
||||
|
||||
public static Class<?> getClassByEngineKey(String engineKey) {
|
||||
return classMap.get(engineKey);
|
||||
}
|
||||
}
|
|
@ -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<String, Object> params){
|
||||
|
||||
Object instance = EngineContainer.getInstance(engineKey);
|
||||
Method method = EngineContainer.getMethodByClass(engineKey);
|
||||
List<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<String, Class<?>> loadClassByLocation(String pack, String location) {
|
||||
//列出所有的class文件
|
||||
List<File> classFiles = FileLoadUtil.getClassFiles(location + FileConstants.FILE_DELIMITER + pack.replaceAll("\\.", FileConstants.FILE_DELIMITER));
|
||||
log.info("class文件---->{}", JSON.toJSONString(classFiles));
|
||||
HashMap<String, Class<?>> 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)));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<File> 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<? extends JavaFileObject> javaFileObjects = fileManager.getJavaFileObjects(file);
|
||||
//生成编译任务
|
||||
log.info("程序运行地址为: {}", path);
|
||||
List<String> 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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<File> 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<File> getClassFiles(String folderPath) {
|
||||
File folder = new File(folderPath);
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs();
|
||||
}
|
||||
File[] files = folder.listFiles();
|
||||
List<File> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, String> PROPER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = PropertiesUtil.class.getClassLoader().getResourceAsStream("application.properties");
|
||||
props.load(is);
|
||||
|
||||
Iterator<Object> 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"));
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-rule-engine</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>etl-rule-remote</artifactId>
|
||||
<version>3.6.5</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>etl-rule-common</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -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<DataStructure[][]> executionGroupRuleVersion(@PathVariable("engineKey") String engineKey, @RequestBody DataStructure[][] dataStructureRows);
|
||||
|
||||
}
|
|
@ -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<RemoteRuleVersion> {
|
||||
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<DataStructure[][]> executionGroupRuleVersion(String engineKey, DataStructure[][] dataStructureRows) {
|
||||
return Result.error("查询数据失败:"+cause.getMessage());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
com.muyu.etl.rule.remote.factory.RemoteRuleVersionBackFactory
|
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-rule-engine</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>etl-rule-server</artifactId>
|
||||
<version>3.6.5</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-common-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>etl-datasource-remote</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</dependency>
|
||||
<!-- SpringCloud Alibaba Nacos -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringCloud Alibaba Nacos Config -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringCloud Alibaba Sentinel -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot Actuator -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql Connector -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MuYu Common DataSource -->
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-common-datasource</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MuYu Common DataScope -->
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-common-datascope</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MuYu Common Log -->
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-common-log</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- XllJob定时任务 -->
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-common-xxl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>etl-rule-common</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>cloud-rule-engine</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>3.2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- 加入maven deploy插件,当deploy时,忽略model -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -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<DataStructure[]> arrayUtil = new ArrayUtil<>(dataStructuresList);
|
||||
while (arrayUtil.hasNext()){
|
||||
DataStructure[] dataStructures = arrayUtil.next();
|
||||
List<DataStructure> dataStructureList = Arrays.stream(dataStructures).filter(dataStructure -> dataStructure.getKey().equals("name") && dataStructure.getValue() == null).toList();
|
||||
if (dataStructureList.size() > 0){
|
||||
arrayUtil.remove();
|
||||
}
|
||||
}
|
||||
set(arrayUtil.getCurrentArray());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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<TableDataInfo<EtlRuleListResp>> list(@RequestBody EtlRuleListReq ruleInfoReq) {
|
||||
startPage();
|
||||
List<RuleInfo> 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<RuleInfo> list = ruleInfoService.selectRuleInfoList(ruleInfoReq);
|
||||
ExcelUtil<RuleInfo> util = new ExcelUtil<RuleInfo>(RuleInfo.class);
|
||||
util.exportExcel(response, list, "规则维护数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取规则维护详细信息
|
||||
*/
|
||||
@RequiresPermissions("engine:ruleInfo:query")
|
||||
@GetMapping(value = "/{id}")
|
||||
@Operation(summary = "获取规则维护详细信息", description = "根据规则维护id获取规则维护详细信息")
|
||||
public Result<EtlRuleListResp> 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<Integer> 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<Integer> 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<Integer> remove(@PathVariable("ids") Long[] ids) {
|
||||
ruleInfoService.removeBatchByIds(Arrays.asList(ids));
|
||||
return success();
|
||||
}
|
||||
}
|
|
@ -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<TableDataInfo<RuleVersion>> list(@RequestBody RuleVersion ruleVersion) {
|
||||
startPage();
|
||||
List<RuleVersion> 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<RuleVersion> list = ruleVersionService.selectRuleVersionList(ruleVersion);
|
||||
ExcelUtil<RuleVersion> util = new ExcelUtil<RuleVersion>(RuleVersion.class);
|
||||
util.exportExcel(response, list, "规则版本数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取规则版本详细信息
|
||||
*/
|
||||
@RequiresPermissions("engine:ruleVersion:query")
|
||||
@GetMapping(value = "/{id}")
|
||||
@Operation(summary = "获取规则版本详细信息", description = "根据规则版本id获取规则版本详细信息")
|
||||
public Result<List<RuleVersion>> getInfo(@PathVariable("id") Long id) {
|
||||
return success(ruleVersionService.selectRuleVersionById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增规则版本
|
||||
*/
|
||||
@RequiresPermissions("engine:ruleVersion:add")
|
||||
@PostMapping
|
||||
@Operation(summary = "新增规则版本", description = "根据规则版本请求参数新增规则版本")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result<Integer> 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<Integer> 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<Integer> 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<String> 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<DataStructure> 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<DataStructure[][]> 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<DataStructure[][]> executionGroupRuleVersion(@PathVariable("engineKey") String engineKey, @RequestBody DataStructure[][] dataStructureRows) {
|
||||
return Result.success(ruleVersionService.executionRowsRuleVersion(engineKey, dataStructureRows));
|
||||
}
|
||||
|
||||
/**
|
||||
* 库表远调二级联动
|
||||
* @return 库表的二级联动
|
||||
*/
|
||||
@GetMapping("/dataSource/tableInfo")
|
||||
@Operation(summary = "库表远调二级联动", description = "数据接入课表接入的二级联动,方便数据的选择")
|
||||
public Result<List<TableInfoResp>> dataSourceList() {
|
||||
return Result.success(ruleVersionService.dataSourceList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表结构
|
||||
* @param id 表id
|
||||
* @return 数据表结构
|
||||
*/
|
||||
@GetMapping("/dataSource/table/{id}")
|
||||
public Result<List<DataAnalysis>> dataSource(@PathVariable("id") Long id) {
|
||||
return Result.success(ruleVersionService.dataFindById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表数据
|
||||
* @param dataTestReq 数据测试请求对象
|
||||
* @return ktlv数据结构
|
||||
*/
|
||||
@PostMapping("/getEtlTableData")
|
||||
public Result<List<List<DataStructure>>> getEtlTableData(@RequestBody DataTestReq dataTestReq) {
|
||||
return Result.success(ruleVersionService.testData(dataTestReq));
|
||||
}
|
||||
|
||||
@GetMapping("/isClassExist/{className}")
|
||||
public Result<Boolean> isClassExist(@PathVariable("className") String className) {
|
||||
return Result.success(ruleVersionService.isClassExist(className));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查詢所有規則(字段,数据集,记录)规则下拉框
|
||||
* @return List<RuleInfo>
|
||||
*/
|
||||
@GetMapping("/getEtlRuleAll")
|
||||
public Result<List<RuleInfo>> getEtlRuleTypeByRuleId() {
|
||||
return Result.success(ruleVersionService.getEtlRuleTypeByRuleId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据规则id查询子规则类型
|
||||
* @param id
|
||||
* @return List<RuleVersion>
|
||||
*/
|
||||
@GetMapping("/getEtlRuleTypeVById")
|
||||
public Result<List<RuleVersion>> getEtlRuleTypeVById(@RequestParam("id") Long id) {
|
||||
return Result.success(ruleVersionService.getEtlRuleTypeVById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据版本类型id查询 返回版本类型对象
|
||||
* @param id
|
||||
* @return RuleVersion
|
||||
*/
|
||||
@GetMapping("/getETlRuleTypeVersionById")
|
||||
public Result<RuleVersion> getETlRuleTypeVersionById(@RequestParam("id") Long id) {
|
||||
return Result.success( ruleVersionService.getById(id));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<RuleInfo>{
|
||||
|
||||
List<RuleInfo> selectRuleInfoList(EtlRuleListReq ruleInfoReq);
|
||||
}
|
|
@ -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<RuleVersion>{
|
||||
|
||||
}
|
|
@ -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<T> implements Iterator<T> {
|
||||
|
||||
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<DataStructure> 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));
|
||||
|
||||
}
|
||||
}
|
|
@ -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<RuleInfo> {
|
||||
/**
|
||||
* 精确查询规则维护
|
||||
*
|
||||
* @param id 规则维护主键
|
||||
* @return 规则维护
|
||||
*/
|
||||
public RuleInfo selectRuleInfoById(Long id);
|
||||
|
||||
/**
|
||||
* 查询规则维护列表
|
||||
* @param ruleInfoReq 规则维护
|
||||
* @return 规则维护集合
|
||||
*/
|
||||
public List<RuleInfo> selectRuleInfoList(EtlRuleListReq ruleInfoReq);
|
||||
|
||||
/**
|
||||
* 判断 规则维护 id是否唯一
|
||||
* @param ruleInfo 规则维护
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean checkIdUnique(RuleInfo ruleInfo);
|
||||
|
||||
}
|
|
@ -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<RuleVersion> {
|
||||
/**
|
||||
* 精确查询规则版本
|
||||
*
|
||||
* @param id 规则版本主键
|
||||
* @return 规则版本
|
||||
*/
|
||||
public RuleVersion selectRuleVersionById(Long id);
|
||||
|
||||
/**
|
||||
* 查询规则版本列表
|
||||
*
|
||||
* @param ruleVersion 规则版本
|
||||
* @return 规则版本集合
|
||||
*/
|
||||
public List<RuleVersion> selectRuleVersionList(RuleVersion ruleVersion);
|
||||
|
||||
/**
|
||||
* 判断 规则版本 id是否唯一
|
||||
* @param ruleVersion 规则版本
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean checkIdUnique(RuleVersion ruleVersion);
|
||||
|
||||
/**
|
||||
* 通过规则id查询规则版本集合
|
||||
* @param id 规则id
|
||||
* @return 规则版本数据集
|
||||
*/
|
||||
List<RuleVersion> 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<TableInfoResp> dataSourceList();
|
||||
|
||||
|
||||
/**
|
||||
* 根据id查询数据表详情
|
||||
* @param id 表id
|
||||
* @return 表结构
|
||||
*/
|
||||
List<DataAnalysis> dataFindById(Long id);
|
||||
|
||||
/**
|
||||
* 测试数据
|
||||
* @param dataTestReq 测试请求参数
|
||||
* @return 测试结果
|
||||
*/
|
||||
List<List<DataStructure>> testData(DataTestReq dataTestReq);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param className
|
||||
* @return
|
||||
*/
|
||||
Boolean isClassExist(String className);
|
||||
/**
|
||||
* 查詢所有規則(字段,数据集,记录)规则下拉框
|
||||
* @return List<RuleInfo>
|
||||
*/
|
||||
List<RuleInfo> getEtlRuleTypeByRuleId();
|
||||
|
||||
|
||||
List<RuleVersion> getEtlRuleTypeVById(Long id);
|
||||
|
||||
|
||||
}
|
|
@ -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<RuleInfoMapper, RuleInfo>
|
||||
implements IRuleInfoService {
|
||||
|
||||
@Resource
|
||||
private RuleInfoMapper ruleInfoMapper;
|
||||
|
||||
/**
|
||||
* 精确查询规则维护
|
||||
*
|
||||
* @param id 规则维护主键
|
||||
* @return 规则维护
|
||||
*/
|
||||
@Override
|
||||
public RuleInfo selectRuleInfoById(Long id)
|
||||
{
|
||||
LambdaQueryWrapper<RuleInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
Assert.notNull(id, "id不可为空");
|
||||
queryWrapper.eq(RuleInfo::getId, id);
|
||||
return this.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询规则维护列表
|
||||
*
|
||||
* @param ruleInfoReq 规则维护
|
||||
* @return 规则维护
|
||||
*/
|
||||
@Override
|
||||
public List<RuleInfo> selectRuleInfoList(EtlRuleListReq ruleInfoReq)
|
||||
{
|
||||
return ruleInfoMapper.selectRuleInfoList(ruleInfoReq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 唯一 判断
|
||||
* @param ruleInfo 规则维护
|
||||
* @return 规则维护
|
||||
*/
|
||||
@Override
|
||||
public Boolean checkIdUnique(RuleInfo ruleInfo) {
|
||||
LambdaQueryWrapper<RuleInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(RuleInfo::getId, ruleInfo.getId());
|
||||
return this.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<RuleVersionMapper, RuleVersion>
|
||||
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<RuleVersion> queryWrapper = new LambdaQueryWrapper<>();
|
||||
Assert.notNull(id, "id不可为空");
|
||||
queryWrapper.eq(RuleVersion::getId, id);
|
||||
return this.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询规则版本列表
|
||||
*
|
||||
* @param ruleVersion 规则版本
|
||||
* @return 规则版本
|
||||
*/
|
||||
@Override
|
||||
public List<RuleVersion> selectRuleVersionList(RuleVersion ruleVersion) {
|
||||
LambdaQueryWrapper<RuleVersion> 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<RuleVersion> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(RuleVersion::getId, ruleVersion.getId());
|
||||
return this.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过规则id查询规则版本
|
||||
*
|
||||
* @param id 规则Id
|
||||
* @return 规则版本数据集合
|
||||
*/
|
||||
@Override
|
||||
public List<RuleVersion> selectRuleVersionListByRuleId(Long id) {
|
||||
LambdaQueryWrapper<RuleVersion> 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<DataStructure[]> 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<TableInfoResp> dataSourceList() {
|
||||
return remoteTableInfoService.findByTableName().getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataAnalysis> dataFindById(Long id) {
|
||||
return remoteDataAnalysisService.findDataAnalysisByTableId(id).getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<DataStructure>> testData(DataTestReq dataTestReq) {
|
||||
return remoteEtlDataService.selEtlData(EtlDataSqlReq.builder()
|
||||
.sql(spliceSql(dataTestReq))
|
||||
.basicId(dataTestReq.getBasicId())
|
||||
.build()).getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isClassExist(String className) {
|
||||
LambdaQueryWrapper<RuleVersion> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(RuleVersion::getRuleVersionClass, className);
|
||||
return this.exists(queryWrapper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 凭借sql
|
||||
*
|
||||
* @param dataTestReq
|
||||
* @return
|
||||
*/
|
||||
private String spliceSql(DataTestReq dataTestReq) {
|
||||
List<String> 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<String, Class<?>> 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> 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<String, Class<?>> 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<String, Object> instanceMap = EngineContainer.instanceMap;
|
||||
Object object = instanceMap.get(engineKey);
|
||||
log.info("返回值对象:object:{}", object);
|
||||
if (object != null && object instanceof BasicEngine<?>) {
|
||||
BasicEngine<T> engine = (BasicEngine<T>) 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<String, Class<?>> 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<String, Object> instanceMap = EngineContainer.instanceMap;
|
||||
// Object object = instanceMap.get(engineKey);
|
||||
// if (object != null && object instanceof BasicEngine<?>) {
|
||||
// BasicEngine<DataStructure> engine = (BasicEngine<DataStructure>) object;
|
||||
// engine.set(dataStructure);
|
||||
// engine.execution();
|
||||
// }
|
||||
|
||||
}
|
||||
/**
|
||||
* 查詢所有規則(字段,数据集,记录)规则下拉框
|
||||
* @return List<RuleInfo>
|
||||
*/
|
||||
@Override
|
||||
public List<RuleInfo> getEtlRuleTypeByRuleId() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuleVersion> getEtlRuleTypeVById(Long id) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Spring Boot Version: ${spring-boot.version}
|
||||
Spring Application Name: ${spring.application.name}
|
|
@ -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
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/etl-rules-engine"/>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.muyu" level="info"/>
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info"/>
|
||||
<appender-ref ref="file_error"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/etl-rules-engine"/>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
|
||||
<property name="log.sky.pattern" value="%d{HH:mm:ss.SSS} %yellow([%tid]) [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.sky.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 使用gRpc将日志发送到skywalking服务端 -->
|
||||
<appender name="GRPC_LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
|
||||
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
|
||||
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
|
||||
<Pattern>${log.sky.pattern}</Pattern>
|
||||
</layout>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.muyu" level="info"/>
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="GRPC_LOG"/>
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info"/>
|
||||
<appender-ref ref="file_error"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/etl-rules-engine"/>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
|
||||
<property name="log.sky.pattern" value="%d{HH:mm:ss.SSS} %yellow([%tid]) [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.sky.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 使用gRpc将日志发送到skywalking服务端 -->
|
||||
<appender name="GRPC_LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
|
||||
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
|
||||
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
|
||||
<Pattern>${log.sky.pattern}</Pattern>
|
||||
</layout>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.muyu" level="info"/>
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="GRPC_LOG"/>
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info"/>
|
||||
<appender-ref ref="file_error"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.muyu.etl.rule.mapper.RuleInfoMapper">
|
||||
|
||||
<resultMap type="com.muyu.etl.rule.domain.RuleInfo" id="RuleInfoResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="ruleName" column="rule_name" />
|
||||
<result property="ruleCode" column="rule_code" />
|
||||
<result property="ruleTypeValue" column="rule_type_value" />
|
||||
<result property="ruleLevelId" column="rule_level_id" />
|
||||
<result property="isActivation" column="is_activation" />
|
||||
<result property="status" column="status" />
|
||||
<result property="ruleExplain" column="rule_explain" />
|
||||
<result property="createBy" column="CREATE_BY" />
|
||||
<result property="createTime" column="CREATE_TIME" />
|
||||
<result property="updateBy" column="UPDATE_BY" />
|
||||
<result property="updateTime" column="UPDATE_TIME" />
|
||||
<result property="remark" column="remark" />
|
||||
<result property="createByName" column="CREATE_BY_NAME" />
|
||||
<result property="updateByName" column="UPDATE_BY_NAME" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectRuleInfoVo">
|
||||
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
|
||||
</sql>
|
||||
|
||||
<select id="selectRuleInfoList" parameterType="com.muyu.etl.rule.domain.RuleInfo" resultMap="RuleInfoResult">
|
||||
<include refid="selectRuleInfoVo"/>
|
||||
<where>
|
||||
<if test="ruleName != null and ruleName != ''"> and rule_name like concat('%', #{ruleName}, '%')</if>
|
||||
<if test="ruleTypeValue != null and ruleTypeValue != ''"> and rule_type_value = #{ruleTypeValue}</if>
|
||||
<if test="isActivation != null and isActivation != ''"> and is_activation = #{isActivation}</if>
|
||||
<if test="status != null and status != ''"> and status = #{status}</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectRuleInfoById" parameterType="Long" resultMap="RuleInfoResult">
|
||||
<include refid="selectRuleInfoVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertRuleInfo" parameterType="com.muyu.etl.rule.domain.RuleInfo" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into etl_rule_info
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="ruleName != null">rule_name,</if>
|
||||
<if test="ruleCode != null">rule_code,</if>
|
||||
<if test="ruleTypeValue != null">rule_type_value,</if>
|
||||
<if test="ruleLevelId != null">rule_level_id,</if>
|
||||
<if test="isActivation != null">is_activation,</if>
|
||||
<if test="status != null">status,</if>
|
||||
<if test="ruleExplain != null">rule_explain,</if>
|
||||
<if test="createBy != null">CREATE_BY,</if>
|
||||
<if test="createTime != null">CREATE_TIME,</if>
|
||||
<if test="updateBy != null">UPDATE_BY,</if>
|
||||
<if test="updateTime != null">UPDATE_TIME,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="createByName != null">CREATE_BY_NAME,</if>
|
||||
<if test="updateByName != null">UPDATE_BY_NAME,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="ruleName != null">#{ruleName},</if>
|
||||
<if test="ruleCode != null">#{ruleCode},</if>
|
||||
<if test="ruleTypeValue != null">#{ruleTypeValue},</if>
|
||||
<if test="ruleLevelId != null">#{ruleLevelId},</if>
|
||||
<if test="isActivation != null">#{isActivation},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
<if test="ruleExplain != null">#{ruleExplain},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="createByName != null">#{createByName},</if>
|
||||
<if test="updateByName != null">#{updateByName},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateRuleInfo" parameterType="com.muyu.etl.rule.domain.RuleInfo">
|
||||
update etl_rule_info
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="ruleName != null">rule_name = #{ruleName},</if>
|
||||
<if test="ruleCode != null">rule_code = #{ruleCode},</if>
|
||||
<if test="ruleTypeValue != null">rule_type_value = #{ruleTypeValue},</if>
|
||||
<if test="ruleLevelId != null">rule_level_id = #{ruleLevelId},</if>
|
||||
<if test="isActivation != null">is_activation = #{isActivation},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
<if test="ruleExplain != null">rule_explain = #{ruleExplain},</if>
|
||||
<if test="createBy != null">CREATE_BY = #{createBy},</if>
|
||||
<if test="createTime != null">CREATE_TIME = #{createTime},</if>
|
||||
<if test="updateBy != null">UPDATE_BY = #{updateBy},</if>
|
||||
<if test="updateTime != null">UPDATE_TIME = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="createByName != null">CREATE_BY_NAME = #{createByName},</if>
|
||||
<if test="updateByName != null">UPDATE_BY_NAME = #{updateByName},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteRuleInfoById" parameterType="Long">
|
||||
delete from etl_rule_info where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteRuleInfoByIds" parameterType="String">
|
||||
delete from etl_rule_info where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
|
@ -0,0 +1,116 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.muyu.etl.rule.mapper.RuleVersionMapper">
|
||||
|
||||
<resultMap type="com.muyu.etl.rule.domain.RuleVersion" id="RuleVersionResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="ruleVersionClass" column="rule_version_class" />
|
||||
<result property="ruleVersionName" column="rule_version_name" />
|
||||
<result property="ruleVersionCode" column="rule_version_code" />
|
||||
<result property="ruleVersionIsActivation" column="rule_version_is_activation" />
|
||||
<result property="ruleVersionIsTest" column="rule_version_is_test" />
|
||||
<result property="ruleVersionStatus" column="rule_version_status" />
|
||||
<result property="ruleVersionDescribed" column="rule_version_described" />
|
||||
<result property="ruleId" column="rule_id" />
|
||||
<result property="createBy" column="CREATE_BY" />
|
||||
<result property="createTime" column="CREATE_TIME" />
|
||||
<result property="updateBy" column="UPDATE_BY" />
|
||||
<result property="updateTime" column="UPDATE_TIME" />
|
||||
<result property="remark" column="remark" />
|
||||
<result property="createByName" column="CREATE_BY_NAME" />
|
||||
<result property="updateByName" column="UPDATE_BY_NAME" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectRuleVersionVo">
|
||||
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
|
||||
</sql>
|
||||
|
||||
<select id="selectRuleVersionList" parameterType="com.muyu.etl.rule.domain.RuleVersion" resultMap="RuleVersionResult">
|
||||
<include refid="selectRuleVersionVo"/>
|
||||
<where>
|
||||
<if test="ruleVersionName != null and ruleVersionName != ''"> and rule_version_name like concat('%', #{ruleVersionName}, '%')</if>
|
||||
<if test="ruleVersionCode != null and ruleVersionCode != ''"> and rule_version_code = #{ruleVersionCode}</if>
|
||||
<if test="ruleVersionIsActivation != null and ruleVersionIsActivation != ''"> and rule_version_is_activation = #{ruleVersionIsActivation}</if>
|
||||
<if test="ruleVersionIsTest != null "> and rule_version_is_test = #{ruleVersionIsTest}</if>
|
||||
<if test="ruleVersionStatus != null "> and rule_version_status = #{ruleVersionStatus}</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectRuleVersionById" parameterType="Long" resultMap="RuleVersionResult">
|
||||
<include refid="selectRuleVersionVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertRuleVersion" parameterType="com.muyu.etl.rule.domain.RuleVersion" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into etl_rule_version
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="ruleVersionClass != null">rule_version_class,</if>
|
||||
<if test="ruleVersionName != null">rule_version_name,</if>
|
||||
<if test="ruleVersionCode != null">rule_version_code,</if>
|
||||
<if test="ruleVersionIsActivation != null">rule_version_is_activation,</if>
|
||||
<if test="ruleVersionIsTest != null">rule_version_is_test,</if>
|
||||
<if test="ruleVersionStatus != null">rule_version_status,</if>
|
||||
<if test="ruleVersionDescribed != null">rule_version_described,</if>
|
||||
<if test="ruleId != null">rule_id,</if>
|
||||
<if test="createBy != null">CREATE_BY,</if>
|
||||
<if test="createTime != null">CREATE_TIME,</if>
|
||||
<if test="updateBy != null">UPDATE_BY,</if>
|
||||
<if test="updateTime != null">UPDATE_TIME,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="createByName != null">CREATE_BY_NAME,</if>
|
||||
<if test="updateByName != null">UPDATE_BY_NAME,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="ruleVersionClass != null">#{ruleVersionClass},</if>
|
||||
<if test="ruleVersionName != null">#{ruleVersionName},</if>
|
||||
<if test="ruleVersionCode != null">#{ruleVersionCode},</if>
|
||||
<if test="ruleVersionIsActivation != null">#{ruleVersionIsActivation},</if>
|
||||
<if test="ruleVersionIsTest != null">#{ruleVersionIsTest},</if>
|
||||
<if test="ruleVersionStatus != null">#{ruleVersionStatus},</if>
|
||||
<if test="ruleVersionDescribed != null">#{ruleVersionDescribed},</if>
|
||||
<if test="ruleId != null">#{ruleId},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="createByName != null">#{createByName},</if>
|
||||
<if test="updateByName != null">#{updateByName},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateRuleVersion" parameterType="com.muyu.etl.rule.domain.RuleVersion">
|
||||
update etl_rule_version
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="ruleVersionClass != null">rule_version_class = #{ruleVersionClass},</if>
|
||||
<if test="ruleVersionName != null">rule_version_name = #{ruleVersionName},</if>
|
||||
<if test="ruleVersionCode != null">rule_version_code = #{ruleVersionCode},</if>
|
||||
<if test="ruleVersionIsActivation != null">rule_version_is_activation = #{ruleVersionIsActivation},</if>
|
||||
<if test="ruleVersionIsTest != null">rule_version_is_test = #{ruleVersionIsTest},</if>
|
||||
<if test="ruleVersionStatus != null">rule_version_status = #{ruleVersionStatus},</if>
|
||||
<if test="ruleVersionDescribed != null">rule_version_described = #{ruleVersionDescribed},</if>
|
||||
<if test="ruleId != null">rule_id = #{ruleId},</if>
|
||||
<if test="createBy != null">CREATE_BY = #{createBy},</if>
|
||||
<if test="createTime != null">CREATE_TIME = #{createTime},</if>
|
||||
<if test="updateBy != null">UPDATE_BY = #{updateBy},</if>
|
||||
<if test="updateTime != null">UPDATE_TIME = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="createByName != null">CREATE_BY_NAME = #{createByName},</if>
|
||||
<if test="updateByName != null">UPDATE_BY_NAME = #{updateByName},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteRuleVersionById" parameterType="Long">
|
||||
delete from etl_rule_version where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteRuleVersionByIds" parameterType="String">
|
||||
delete from etl_rule_version where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>cloud-modules</artifactId>
|
||||
<version>3.6.5</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>cloud-rule-engine</artifactId>
|
||||
<version>3.6.5</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>etl-rule-common</module>
|
||||
<module>etl-rule-remote</module>
|
||||
<module>etl-rule-server</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>yun-releases</id>
|
||||
<name>yun-releases</name>
|
||||
<url>http://10.0.1.3:8081/repository/maven-releases/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</project>
|
Loading…
Reference in New Issue