add 新增规则引擎

This commit is contained in:
AprilWind 2024-06-21 14:46:51 +08:00
parent 0b331796e2
commit 7ca1eef232
32 changed files with 1837 additions and 0 deletions

84
pom.xml
View File

@ -59,6 +59,9 @@
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
<!-- 规则引擎 -->
<liteflow.version>2.12.1</liteflow.version>
</properties>
<profiles>
@ -339,6 +342,80 @@
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>${liteflow.version}</version>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
<version>${liteflow.version}</version>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-rule-sql</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Groovy脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-groovy</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Javascript脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-graaljs</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Java脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-java</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- QLExpress脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-qlexpress</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Python脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-python</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Lua脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-lua</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Aviator脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-aviator</artifactId>
<version>${liteflow.version}</version>
</dependency>
<!-- Kotlin脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-kotlin</artifactId>
<version>${liteflow.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-system</artifactId>
@ -370,6 +447,13 @@
<version>${revision}</version>
</dependency>
<!-- 规则引擎模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-liteflow</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -86,6 +86,12 @@
<artifactId>ruoyi-workflow</artifactId>
</dependency>
<!-- 规则引擎 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-liteflow</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>

View File

@ -285,3 +285,56 @@ flowable:
enabled: false
app:
enabled: false
--- # 规则引擎
liteflow:
# 组件降级
fallback-cmp-enable: true
# 执行过程中的日志
print-execution-log: true
# 5000条规则以上的时候开启可将加载性能能提高4倍
fast-load: false
# 默认线程池的worker数目
parallel-max-workers: 16
# 默认线程池的队列长度
parallel-queue-limit: 512
# 指定自定义的线程池全类名的方式指定异步循环线程池
# parallel-loop-executor-class:
# 启动时不解析规则,但是第一次执行相关规则时,只解析对应的规则
parse-mode: PARSE_ONE_ON_FIRST_EXEC
rule-source-ext-data-map:
applicationName: @profiles.active@
# 编排规则表
chainTableName: liteflow_chain
# 应用名称存储字段名
chainApplicationNameField: application_name
# 规则名称存储的字段名
chainNameField: chain_name
# EL表达式的字段(只存EL)
elDataField: el_str
# 决策路由EL字段
routeField: route
# namespace字段
namespaceField: name_space
# 是否生效 1为生效0为不生效
chainEnableField: chain_status
# 脚本存储表的表名
scriptTableName: liteflow_script
# 应用名称存储字段名
scriptApplicationNameField: application_name
# 脚本组件的Id的字段名
scriptIdField: script_id
# 脚本组件名称的字段名
scriptNameField: script_name
# 脚本数据的字段名
scriptDataField: script_data
# 脚本类型的字段名
scriptTypeField: script_type
# 脚本语言类型groovy | qlexpress | js | python | lua | aviator | java | kotlin
scriptLanguageField: script_language
# 是否生效 1为生效0为不生效
scriptEnableField: script_status
#以下是轮询机制的配置
pollingEnabled: true
pollingStartSeconds: 600
pollingIntervalSeconds: 600

View File

@ -20,6 +20,7 @@
<module>ruoyi-common-log</module>
<module>ruoyi-common-mail</module>
<module>ruoyi-common-mybatis</module>
<module>ruoyi-common-liteflow</module>
<module>ruoyi-common-oss</module>
<module>ruoyi-common-ratelimiter</module>
<module>ruoyi-common-redis</module>

View File

@ -47,6 +47,13 @@
<version>${revision}</version>
</dependency>
<!-- 规则引擎 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-liteflow</artifactId>
<version>${revision}</version>
</dependency>
<!-- 调度模块 -->
<dependency>
<groupId>org.dromara</groupId>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-liteflow</artifactId>
<description>
ruoyi-common-liteflow 规则引擎
</description>
<dependencies>
<!-- RuoYi Common Core-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-rule-sql</artifactId>
</dependency>
<!-- Lua脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-lua</artifactId>
</dependency>
<!-- Java脚本引擎 -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-script-java</artifactId>
</dependency>
<!-- Groovy脚本引擎 -->
<!-- <dependency>-->
<!-- <groupId>com.yomahub</groupId>-->
<!-- <artifactId>liteflow-script-groovy</artifactId>-->
<!-- </dependency>-->
<!-- Javascript脚本引擎 -->
<!-- <dependency>-->
<!-- <groupId>com.yomahub</groupId>-->
<!-- <artifactId>liteflow-script-graaljs</artifactId>-->
<!-- </dependency>-->
<!-- QLExpress脚本引擎 -->
<!-- <dependency>-->
<!-- <groupId>com.yomahub</groupId>-->
<!-- <artifactId>liteflow-script-qlexpress</artifactId>-->
<!-- </dependency>-->
<!-- python解析执行依赖Jython环境不安装部署启动会报错IDEA里不会报错 -->
<!-- Python脚本引擎 -->
<!-- <dependency>-->
<!-- <groupId>com.yomahub</groupId>-->
<!-- <artifactId>liteflow-script-python</artifactId>-->
<!-- </dependency>-->
<!-- Aviator脚本引擎 -->
<!-- <dependency>-->
<!-- <groupId>com.yomahub</groupId>-->
<!-- <artifactId>liteflow-script-aviator</artifactId>-->
<!-- </dependency>-->
<!-- Kotlin脚本引擎 -->
<!-- <dependency>-->
<!-- <groupId>com.yomahub</groupId>-->
<!-- <artifactId>liteflow-script-kotlin</artifactId>-->
<!-- </dependency>-->
</dependencies>
</project>

View File

@ -0,0 +1,25 @@
package org.dromara.common.liteflow.config;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.liteflow.handler.LiteFlowExceptionHandler;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
* LiteFlow 配置
*
* @author AprilWind
*/
@Slf4j
@AutoConfiguration
public class LiteFlowConfig {
/**
* 异常处理器
*/
@Bean
public LiteFlowExceptionHandler liteFlowExceptionHandler() {
return new LiteFlowExceptionHandler();
}
}

View File

@ -0,0 +1,20 @@
package org.dromara.common.liteflow.constant;
/**
* Liteflow 常量
*
* @author AprilWind
*/
public interface LiteFlowConstants {
/**
* 激活
*/
Integer LITEFLOW_NORMAL = 1;
/**
* 未激活
*/
Integer LITEFLOW_DISABLE = 0;
}

View File

@ -0,0 +1,35 @@
package org.dromara.common.liteflow.entity;
import lombok.Data;
import org.dromara.common.liteflow.enums.LiteflowType;
import java.io.Serial;
import java.io.Serializable;
/**
* 规则引擎事件
*
* @author AprilWind
*/
@Data
public class LiteflowFlowBus implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 规则引擎事件类型
*/
private LiteflowType liteflowType;
/**
* 事件关联的ID
*/
private String id;
/**
* 事件的内容
*/
private String content;
}

View File

@ -0,0 +1,36 @@
package org.dromara.common.liteflow.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 规则引擎事件枚举
*
* @author AprilWind
*/
@Getter
@AllArgsConstructor
public enum LiteflowType {
/**
* 重新加载规则
*/
RELOAD_CHAIN("reload_chain"),
/**
* 移除规则
*/
REMOVE_CHAIN("remove_chain"),
/**
* 重新加载脚本
*/
RELOAD_SCRIPT("reload_script"),
/**
* 卸载脚本节点
*/
UNLOAD_SCRIPT("unload_script");
private final String flowBus;
}

View File

@ -0,0 +1,30 @@
package org.dromara.common.liteflow.handler;
import cn.hutool.http.HttpStatus;
import com.yomahub.liteflow.exception.LiteFlowException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* LiteFlow 异常处理器
*
* @author AprilWind
*/
@Slf4j
@RestControllerAdvice
public class LiteFlowExceptionHandler {
/**
* 规则引擎内部逻辑发生错误抛出的异常
*/
@ExceptionHandler(LiteFlowException.class)
public R<Void> handleLockFailureException(LiteFlowException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("处理请求'{}'时发生LiteFlow异常: ", requestURI, e);
return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "系统内部错误,请稍后再试...");
}
}

View File

@ -0,0 +1 @@
org.dromara.common.liteflow.config.LiteFlowConfig

View File

@ -15,6 +15,7 @@
<module>ruoyi-job</module>
<module>ruoyi-system</module>
<module>ruoyi-workflow</module>
<module>ruoyi-liteflow</module>
</modules>
<artifactId>ruoyi-modules</artifactId>

View File

@ -0,0 +1,69 @@
<?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">
<parent>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-liteflow</artifactId>
<description>
liteflow 规则引擎
</description>
<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<!-- excel-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-excel</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-web</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
</dependency>
<!-- 规则引擎 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-liteflow</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,109 @@
package org.dromara.liteflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.liteflow.domain.bo.LiteflowChainBo;
import org.dromara.liteflow.domain.vo.LiteflowChainVo;
import org.dromara.liteflow.service.ILiteflowChainService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 编排规则
*
* @author AprilWind
* @date 2024-06-21
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/liteflow/chain")
public class LiteflowChainController extends BaseController {
private final ILiteflowChainService liteflowChainService;
/**
* 查询编排规则列表
*/
@SaCheckPermission("liteflow:chain:list")
@GetMapping("/list")
public TableDataInfo<LiteflowChainVo> list(LiteflowChainBo bo, PageQuery pageQuery) {
return liteflowChainService.queryPageList(bo, pageQuery);
}
/**
* 导出编排规则列表
*/
@SaCheckPermission("liteflow:chain:export")
@Log(title = "编排规则", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(LiteflowChainBo bo, HttpServletResponse response) {
List<LiteflowChainVo> list = liteflowChainService.queryList(bo);
ExcelUtil.exportExcel(list, "编排规则", LiteflowChainVo.class, response);
}
/**
* 获取编排规则详细信息
*
* @param id 主键
*/
@SaCheckPermission("liteflow:chain:query")
@GetMapping("/{id}")
public R<LiteflowChainVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(liteflowChainService.queryById(id));
}
/**
* 新增编排规则
*/
@SaCheckPermission("liteflow:chain:add")
@Log(title = "编排规则", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody LiteflowChainBo bo) {
if (!liteflowChainService.checkChainNameUnique(bo)) {
return R.fail("新增编排规则'" + bo.getChainName() + "'失败,规则名称已存在");
}
return toAjax(liteflowChainService.insertByBo(bo));
}
/**
* 修改编排规则
*/
@SaCheckPermission("liteflow:chain:edit")
@Log(title = "编排规则", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody LiteflowChainBo bo) {
return toAjax(liteflowChainService.updateByBo(bo));
}
/**
* 删除编排规则
*
* @param ids 主键串
*/
@SaCheckPermission("liteflow:chain:remove")
@Log(title = "编排规则", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(liteflowChainService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,109 @@
package org.dromara.liteflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.liteflow.domain.bo.LiteflowScriptBo;
import org.dromara.liteflow.domain.vo.LiteflowScriptVo;
import org.dromara.liteflow.service.ILiteflowScriptService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 脚本
*
* @author AprilWind
* @date 2024-06-21
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/liteflow/script")
public class LiteflowScriptController extends BaseController {
private final ILiteflowScriptService liteflowScriptService;
/**
* 查询脚本列表
*/
@SaCheckPermission("liteflow:script:list")
@GetMapping("/list")
public TableDataInfo<LiteflowScriptVo> list(LiteflowScriptBo bo, PageQuery pageQuery) {
return liteflowScriptService.queryPageList(bo, pageQuery);
}
/**
* 导出脚本列表
*/
@SaCheckPermission("liteflow:script:export")
@Log(title = "脚本", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(LiteflowScriptBo bo, HttpServletResponse response) {
List<LiteflowScriptVo> list = liteflowScriptService.queryList(bo);
ExcelUtil.exportExcel(list, "脚本", LiteflowScriptVo.class, response);
}
/**
* 获取脚本详细信息
*
* @param id 主键
*/
@SaCheckPermission("liteflow:script:query")
@GetMapping("/{id}")
public R<LiteflowScriptVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(liteflowScriptService.queryById(id));
}
/**
* 新增脚本
*/
@SaCheckPermission("liteflow:script:add")
@Log(title = "脚本", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody LiteflowScriptBo bo) {
if (!liteflowScriptService.checkScriptIdUnique(bo)) {
return R.fail("新增脚本'" + bo.getScriptId() + "'失败脚本ID已存在");
}
return toAjax(liteflowScriptService.insertByBo(bo));
}
/**
* 修改脚本
*/
@SaCheckPermission("liteflow:script:edit")
@Log(title = "脚本", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody LiteflowScriptBo bo) {
return toAjax(liteflowScriptService.updateByBo(bo));
}
/**
* 删除脚本
*
* @param ids 主键串
*/
@SaCheckPermission("liteflow:script:remove")
@Log(title = "脚本", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(liteflowScriptService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,74 @@
package org.dromara.liteflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
/**
* 编排规则对象 liteflow_chain
*
* @author AprilWind
* @date 2024-06-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("liteflow_chain")
public class LiteflowChain extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id")
private Long id;
/**
* 配置环境
*/
private String applicationName;
/**
* 编排规则ID
*/
private String chainName;
/**
* 状态0未激活 1激活
*/
private Integer chainStatus;
/**
* EL表达式
*/
private String elStr;
/**
* namespace决策路由很多想要判断某一组决策路由时在chain层面加入namespace参数
*/
private String nameSpace;
/**
* 决策路由EL
*/
private String route;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,79 @@
package org.dromara.liteflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
/**
* 脚本对象 liteflow_script
*
* @author AprilWind
* @date 2024-06-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("liteflow_script")
public class LiteflowScript extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id")
private Long id;
/**
* 配置环境
*/
private String applicationName;
/**
* 脚本ID
*/
private String scriptId;
/**
* 脚本名称
*/
private String scriptName;
/**
* 脚本语言类型groovy | qlexpress | js | python | lua | aviator | java | kotlin
*/
private String scriptLanguage;
/**
* 脚本类型(script普通脚本节点脚本里无需返回 switch_script选择脚本节点脚本里需要返回选择的节点Id boolean_script条件脚本节点脚本里需要返回true/false for_script数量循环节点脚本里需要返回数值类型表示循环次数)
*/
private String scriptType;
/**
* 状态0未激活 1激活
*/
private Integer scriptStatus;
/**
* 脚本内容
*/
private String scriptData;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,69 @@
package org.dromara.liteflow.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.liteflow.domain.LiteflowChain;
/**
* 编排规则业务对象 liteflow_chain
*
* @author AprilWind
* @date 2024-06-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = LiteflowChain.class, reverseConvertGenerate = false)
public class LiteflowChainBo extends BaseEntity {
/**
* id
*/
@NotNull(message = "id不能为空", groups = {EditGroup.class})
private Long id;
/**
* 配置环境
*/
@NotBlank(message = "配置环境不能为空", groups = {AddGroup.class})
private String applicationName;
/**
* 编排规则ID
*/
@NotBlank(message = "编排规则ID不能为空", groups = {AddGroup.class})
private String chainName;
/**
* 状态0未激活 1激活
*/
private Integer chainStatus;
/**
* EL表达式
*/
@NotBlank(message = "EL表达式不能为空", groups = {AddGroup.class, EditGroup.class})
private String elStr;
/**
* namespace决策路由很多想要判断某一组决策路由时在chain层面加入namespace参数
*/
private String nameSpace;
/**
* 决策路由EL
*/
private String route;
/**
* 备注
*/
@NotBlank(message = "备注不能为空", groups = {AddGroup.class, EditGroup.class})
private String remark;
}

View File

@ -0,0 +1,77 @@
package org.dromara.liteflow.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.liteflow.domain.LiteflowScript;
/**
* 脚本业务对象 liteflow_script
*
* @author AprilWind
* @date 2024-06-21
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = LiteflowScript.class, reverseConvertGenerate = false)
public class LiteflowScriptBo extends BaseEntity {
/**
* id
*/
@NotNull(message = "id不能为空", groups = {EditGroup.class})
private Long id;
/**
* 配置环境
*/
@NotBlank(message = "配置环境不能为空", groups = {AddGroup.class})
private String applicationName;
/**
* 脚本ID
*/
@NotBlank(message = "脚本ID不能为空", groups = {AddGroup.class})
private String scriptId;
/**
* 脚本名称
*/
@NotBlank(message = "脚本名称不能为空", groups = {AddGroup.class})
private String scriptName;
/**
* 脚本语言类型groovy | qlexpress | js | python | lua | aviator | java | kotlin
*/
@NotBlank(message = "脚本语言类型不能为空", groups = {AddGroup.class})
private String scriptLanguage;
/**
* 脚本类型(script普通脚本节点脚本里无需返回 switch_script选择脚本节点脚本里需要返回选择的节点Id boolean_script条件脚本节点脚本里需要返回true/false for_script数量循环节点脚本里需要返回数值类型表示循环次数)
*/
@NotBlank(message = "脚本类型不能为空", groups = {AddGroup.class})
private String scriptType;
/**
* 状态0未激活 1激活
*/
private Integer scriptStatus;
/**
* 脚本内容
*/
@NotBlank(message = "脚本内容不能为空", groups = {AddGroup.class, EditGroup.class})
private String scriptData;
/**
* 备注
*/
@NotBlank(message = "备注不能为空", groups = {AddGroup.class, EditGroup.class})
private String remark;
}

View File

@ -0,0 +1,78 @@
package org.dromara.liteflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.liteflow.domain.LiteflowChain;
import java.io.Serial;
import java.io.Serializable;
/**
* 编排规则视图对象 liteflow_chain
*
* @author AprilWind
* @date 2024-06-21
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = LiteflowChain.class)
public class LiteflowChainVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@ExcelProperty(value = "id")
private Long id;
/**
* 配置环境
*/
@ExcelProperty(value = "配置环境")
private String applicationName;
/**
* 编排规则ID
*/
@ExcelProperty(value = "编排规则ID")
private String chainName;
/**
* 状态0未激活 1激活
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=未激活,1=激活")
private Integer chainStatus;
/**
* EL表达式
*/
@ExcelProperty(value = "EL表达式")
private String elStr;
/**
* namespace决策路由很多想要判断某一组决策路由时在chain层面加入namespace参数
*/
@ExcelProperty(value = "namespace", converter = ExcelDictConvert.class)
private String nameSpace;
/**
* 决策路由EL
*/
@ExcelProperty(value = "决策路由EL")
private String route;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,83 @@
package org.dromara.liteflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.liteflow.domain.LiteflowScript;
import java.io.Serial;
import java.io.Serializable;
/**
* 脚本视图对象 liteflow_script
*
* @author AprilWind
* @date 2024-06-21
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = LiteflowScript.class)
public class LiteflowScriptVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@ExcelProperty(value = "id")
private Long id;
/**
* 配置环境
*/
@ExcelProperty(value = "配置环境")
private String applicationName;
/**
* 脚本ID
*/
@ExcelProperty(value = "脚本ID")
private String scriptId;
/**
* 脚本名称
*/
@ExcelProperty(value = "脚本名称")
private String scriptName;
/**
* 脚本语言类型groovy | qlexpress | js | python | lua | aviator | java | kotlin
*/
@ExcelProperty(value = "脚本语言类型", converter = ExcelDictConvert.class)
private String scriptLanguage;
/**
* 脚本类型(script普通脚本节点脚本里无需返回 switch_script选择脚本节点脚本里需要返回选择的节点Id boolean_script条件脚本节点脚本里需要返回true/false for_script数量循环节点脚本里需要返回数值类型表示循环次数)
*/
@ExcelProperty(value = "脚本类型")
private String scriptType;
/**
* 状态0未激活 1激活
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=未激活,1=激活")
private Integer scriptStatus;
/**
* 脚本内容
*/
@ExcelProperty(value = "脚本内容")
private String scriptData;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,79 @@
package org.dromara.liteflow.listener;
import com.yomahub.liteflow.flow.FlowBus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.liteflow.entity.LiteflowFlowBus;
import org.dromara.common.liteflow.enums.LiteflowType;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 规则引擎 侦听器
*
* @author AprilWind
* @date 2024-06-21
*/
@RequiredArgsConstructor
@Component
@Slf4j
public class LiteflowListener {
/**
* 处理规则引擎事件
*
* @param liteflowFlowBus 包含规则引擎事件信息的对象
*/
@Async
@EventListener
public void handleLiteflowEvent(LiteflowFlowBus liteflowFlowBus) {
// 获取事件的类型
LiteflowType flowBusType = liteflowFlowBus.getLiteflowType();
// 获取事件关联的ID
String id = liteflowFlowBus.getId();
// 获取事件的内容
String content = liteflowFlowBus.getContent();
// 根据事件类型执行相应的操作
switch (flowBusType) {
case RELOAD_CHAIN:
// 重新加载链式规则
FlowBus.reloadChain(id, content);
log.info("重新加载链式规则:{}", id);
break;
case REMOVE_CHAIN:
// 移除链式规则
FlowBus.removeChain(id);
log.info("移除链式规则:{}", id);
break;
case RELOAD_SCRIPT:
// 重新加载脚本
FlowBus.reloadScript(id, content);
log.info("重新加载脚本:{}", id);
break;
case UNLOAD_SCRIPT:
// 卸载脚本节点
FlowBus.unloadScriptNode(id);
log.info("卸载脚本节点:{}", id);
break;
default:
log.error("未知的LiteflowType: {}", flowBusType);
}
}
/**
* 异步处理规则引擎事件列表
* 注意虽然方法标记了 @Async 注解但内部的方法调用不会异步执行需要手动使用 TaskExecutor 实现异步
*
* @param liteflowFlowBus 包含规则引擎事件信息的对象列表
*/
@Async
@EventListener
public void handleLiteflowEvent(List<LiteflowFlowBus> liteflowFlowBus) {
liteflowFlowBus.forEach(this::handleLiteflowEvent);
}
}

View File

@ -0,0 +1,15 @@
package org.dromara.liteflow.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.liteflow.domain.LiteflowChain;
import org.dromara.liteflow.domain.vo.LiteflowChainVo;
/**
* 编排规则Mapper接口
*
* @author AprilWind
* @date 2024-06-21
*/
public interface LiteflowChainMapper extends BaseMapperPlus<LiteflowChain, LiteflowChainVo> {
}

View File

@ -0,0 +1,15 @@
package org.dromara.liteflow.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.liteflow.domain.LiteflowScript;
import org.dromara.liteflow.domain.vo.LiteflowScriptVo;
/**
* 脚本Mapper接口
*
* @author AprilWind
* @date 2024-06-21
*/
public interface LiteflowScriptMapper extends BaseMapperPlus<LiteflowScript, LiteflowScriptVo> {
}

View File

@ -0,0 +1,76 @@
package org.dromara.liteflow.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.liteflow.domain.bo.LiteflowChainBo;
import org.dromara.liteflow.domain.vo.LiteflowChainVo;
import java.util.Collection;
import java.util.List;
/**
* 编排规则Service接口
*
* @author AprilWind
* @date 2024-06-21
*/
public interface ILiteflowChainService {
/**
* 查询编排规则
*
* @param id 主键
* @return 编排规则
*/
LiteflowChainVo queryById(Long id);
/**
* 分页查询编排规则列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 编排规则分页列表
*/
TableDataInfo<LiteflowChainVo> queryPageList(LiteflowChainBo bo, PageQuery pageQuery);
/**
* 查询符合条件的编排规则列表
*
* @param bo 查询条件
* @return 编排规则列表
*/
List<LiteflowChainVo> queryList(LiteflowChainBo bo);
/**
* 校验编排规则ID是否唯一
*
* @param chain 规则信息
* @return 结果true表示唯一false表示不唯一
*/
boolean checkChainNameUnique(LiteflowChainBo chain);
/**
* 新增编排规则
*
* @param bo 编排规则
* @return 是否新增成功
*/
Boolean insertByBo(LiteflowChainBo bo);
/**
* 修改编排规则
*
* @param bo 编排规则
* @return 是否修改成功
*/
Boolean updateByBo(LiteflowChainBo bo);
/**
* 校验并批量删除编排规则信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,76 @@
package org.dromara.liteflow.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.liteflow.domain.bo.LiteflowScriptBo;
import org.dromara.liteflow.domain.vo.LiteflowScriptVo;
import java.util.Collection;
import java.util.List;
/**
* 脚本Service接口
*
* @author AprilWind
* @date 2024-06-21
*/
public interface ILiteflowScriptService {
/**
* 查询脚本
*
* @param id 主键
* @return 脚本
*/
LiteflowScriptVo queryById(Long id);
/**
* 分页查询脚本列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 脚本分页列表
*/
TableDataInfo<LiteflowScriptVo> queryPageList(LiteflowScriptBo bo, PageQuery pageQuery);
/**
* 查询符合条件的脚本列表
*
* @param bo 查询条件
* @return 脚本列表
*/
List<LiteflowScriptVo> queryList(LiteflowScriptBo bo);
/**
* 校验脚本ID是否唯一
*
* @param script 脚本信息
* @return 结果true表示唯一false表示不唯一
*/
boolean checkScriptIdUnique(LiteflowScriptBo script);
/**
* 新增脚本
*
* @param bo 脚本
* @return 是否新增成功
*/
Boolean insertByBo(LiteflowScriptBo bo);
/**
* 修改脚本
*
* @param bo 脚本
* @return 是否修改成功
*/
Boolean updateByBo(LiteflowScriptBo bo);
/**
* 校验并批量删除脚本信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,191 @@
package org.dromara.liteflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.liteflow.entity.LiteflowFlowBus;
import org.dromara.common.liteflow.enums.LiteflowType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.liteflow.domain.LiteflowChain;
import org.dromara.liteflow.domain.bo.LiteflowChainBo;
import org.dromara.liteflow.domain.vo.LiteflowChainVo;
import org.dromara.liteflow.mapper.LiteflowChainMapper;
import org.dromara.liteflow.service.ILiteflowChainService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.dromara.common.liteflow.constant.LiteFlowConstants.LITEFLOW_DISABLE;
import static org.dromara.common.liteflow.constant.LiteFlowConstants.LITEFLOW_NORMAL;
/**
* 编排规则Service业务层处理
*
* @author AprilWind
* @date 2024-06-21
*/
@RequiredArgsConstructor
@Service
public class LiteflowChainServiceImpl implements ILiteflowChainService {
private final LiteflowChainMapper baseMapper;
/**
* 查询编排规则
*
* @param id 主键
* @return 编排规则
*/
@Override
public LiteflowChainVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询编排规则列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 编排规则分页列表
*/
@Override
public TableDataInfo<LiteflowChainVo> queryPageList(LiteflowChainBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<LiteflowChain> lqw = buildQueryWrapper(bo);
Page<LiteflowChainVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的编排规则列表
*
* @param bo 查询条件
* @return 编排规则列表
*/
@Override
public List<LiteflowChainVo> queryList(LiteflowChainBo bo) {
LambdaQueryWrapper<LiteflowChain> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<LiteflowChain> buildQueryWrapper(LiteflowChainBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<LiteflowChain> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getApplicationName()), LiteflowChain::getApplicationName, bo.getApplicationName());
lqw.eq(StringUtils.isNotBlank(bo.getChainName()), LiteflowChain::getChainName, bo.getChainName());
lqw.eq(bo.getChainStatus() != null, LiteflowChain::getChainStatus, bo.getChainStatus());
lqw.eq(StringUtils.isNotBlank(bo.getNameSpace()), LiteflowChain::getNameSpace, bo.getNameSpace());
lqw.like(StringUtils.isNotBlank(bo.getRemark()), LiteflowChain::getRemark, bo.getRemark());
return lqw;
}
/**
* 校验编排规则ID是否唯一
*
* @param chain 规则信息
* @return 结果true表示唯一false表示不唯一
*/
@Override
public boolean checkChainNameUnique(LiteflowChainBo chain) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<LiteflowChain>()
.eq(LiteflowChain::getApplicationName, chain.getApplicationName())
.eq(LiteflowChain::getChainName, chain.getChainName())
.ne(ObjectUtil.isNotNull(chain.getId()), LiteflowChain::getId, chain.getId()));
return !exist;
}
/**
* 新增编排规则
*
* @param bo 编排规则
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(LiteflowChainBo bo) {
LiteflowChain add = MapstructUtils.convert(bo, LiteflowChain.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改编排规则
*
* @param bo 编排规则
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(LiteflowChainBo bo) {
LiteflowChain update = MapstructUtils.convert(bo, LiteflowChain.class);
validEntityBeforeSave(update);
LiteflowChainVo vo = baseMapper.selectVoById(bo.getId());
if (LITEFLOW_NORMAL.equals(vo.getChainStatus())) {
LiteflowFlowBus bus = new LiteflowFlowBus();
bus.setId(vo.getChainName());
if (LITEFLOW_DISABLE.equals(update.getChainStatus())) {
bus.setLiteflowType(LiteflowType.REMOVE_CHAIN);
} else {
bus.setLiteflowType(LiteflowType.RELOAD_CHAIN);
bus.setContent(update.getElStr());
}
SpringUtils.context().publishEvent(bus);
}
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(LiteflowChain entity) {
// 校验EL表达式
if (!LiteFlowChainELBuilder.validate(entity.getElStr())) {
throw new ServiceException("EL表达式校验失败");
}
// 如果路由不为空校验路由
if (StringUtils.isNotBlank(entity.getRoute()) && !LiteFlowChainELBuilder.validate(entity.getRoute())) {
throw new ServiceException("决策路由EL校验失败");
}
}
/**
* 校验并批量删除编排规则信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
List<LiteflowChainVo> liteflowChainVos = baseMapper.selectVoList(
new LambdaQueryWrapper<LiteflowChain>().in(LiteflowChain::getId, ids));
if (isValid) {
if (CollUtil.isEmpty(liteflowChainVos)) {
return true;
}
}
List<LiteflowFlowBus> liteflowFlowBus = liteflowChainVos.stream()
.map(x -> {
LiteflowFlowBus flowBus = new LiteflowFlowBus();
flowBus.setLiteflowType(LiteflowType.REMOVE_CHAIN);
flowBus.setId(x.getChainName());
return flowBus;
}).collect(Collectors.toList());
// 发布规则引擎事件
SpringUtils.context().publishEvent(liteflowFlowBus);
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,198 @@
package org.dromara.liteflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yomahub.liteflow.enums.ScriptTypeEnum;
import com.yomahub.liteflow.script.validator.ScriptValidator;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.liteflow.entity.LiteflowFlowBus;
import org.dromara.common.liteflow.enums.LiteflowType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.liteflow.domain.LiteflowScript;
import org.dromara.liteflow.domain.bo.LiteflowScriptBo;
import org.dromara.liteflow.domain.vo.LiteflowScriptVo;
import org.dromara.liteflow.mapper.LiteflowScriptMapper;
import org.dromara.liteflow.service.ILiteflowScriptService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.dromara.common.liteflow.constant.LiteFlowConstants.LITEFLOW_DISABLE;
import static org.dromara.common.liteflow.constant.LiteFlowConstants.LITEFLOW_NORMAL;
/**
* 脚本Service业务层处理
*
* @author AprilWind
* @date 2024-06-21
*/
@RequiredArgsConstructor
@Service
public class LiteflowScriptServiceImpl implements ILiteflowScriptService {
private final LiteflowScriptMapper baseMapper;
/**
* 查询脚本
*
* @param id 主键
* @return 脚本
*/
@Override
public LiteflowScriptVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询脚本列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 脚本分页列表
*/
@Override
public TableDataInfo<LiteflowScriptVo> queryPageList(LiteflowScriptBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<LiteflowScript> lqw = buildQueryWrapper(bo);
Page<LiteflowScriptVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的脚本列表
*
* @param bo 查询条件
* @return 脚本列表
*/
@Override
public List<LiteflowScriptVo> queryList(LiteflowScriptBo bo) {
LambdaQueryWrapper<LiteflowScript> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<LiteflowScript> buildQueryWrapper(LiteflowScriptBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<LiteflowScript> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getApplicationName()), LiteflowScript::getApplicationName, bo.getApplicationName());
lqw.eq(StringUtils.isNotBlank(bo.getScriptId()), LiteflowScript::getScriptId, bo.getScriptId());
lqw.eq(StringUtils.isNotBlank(bo.getScriptName()), LiteflowScript::getScriptName, bo.getScriptName());
lqw.eq(StringUtils.isNotBlank(bo.getScriptLanguage()), LiteflowScript::getScriptLanguage, bo.getScriptLanguage());
lqw.eq(StringUtils.isNotBlank(bo.getScriptType()), LiteflowScript::getScriptType, bo.getScriptType());
lqw.eq(bo.getScriptStatus() != null, LiteflowScript::getScriptStatus, bo.getScriptStatus());
lqw.like(StringUtils.isNotBlank(bo.getRemark()), LiteflowScript::getRemark, bo.getRemark());
return lqw;
}
/**
* 校验脚本ID是否唯一
*
* @param script 脚本信息
* @return 结果true表示唯一false表示不唯一
*/
@Override
public boolean checkScriptIdUnique(LiteflowScriptBo script) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<LiteflowScript>()
.eq(LiteflowScript::getApplicationName, script.getApplicationName())
.eq(LiteflowScript::getScriptId, script.getScriptId())
.ne(ObjectUtil.isNotNull(script.getId()), LiteflowScript::getId, script.getId()));
return !exist;
}
/**
* 新增脚本
*
* @param bo 脚本
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(LiteflowScriptBo bo) {
LiteflowScript add = MapstructUtils.convert(bo, LiteflowScript.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改脚本
*
* @param bo 脚本
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(LiteflowScriptBo bo) {
LiteflowScript update = MapstructUtils.convert(bo, LiteflowScript.class);
validEntityBeforeSave(update);
LiteflowScriptVo vo = baseMapper.selectVoById(update.getId());
if (LITEFLOW_NORMAL.equals(vo.getScriptStatus())) {
LiteflowFlowBus bus = new LiteflowFlowBus();
bus.setId(vo.getScriptId());
if (LITEFLOW_DISABLE.equals(update.getScriptStatus())) {
bus.setLiteflowType(LiteflowType.UNLOAD_SCRIPT);
} else {
bus.setLiteflowType(LiteflowType.RELOAD_SCRIPT);
bus.setContent(update.getScriptData());
}
SpringUtils.context().publishEvent(bus);
}
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(LiteflowScript entity) {
// 检查脚本语言是否合法
if (!ScriptTypeEnum.checkScriptType(entity.getScriptLanguage())) {
throw new ServiceException("脚本语言不合法!");
}
ScriptTypeEnum enumByDisplayName = ScriptTypeEnum.getEnumByDisplayName(entity.getScriptLanguage());
// 验证脚本数据是否符合规范
if (!ScriptValidator.validate(entity.getScriptData(), enumByDisplayName)) {
// 具体错误请查看日志暂不支持返回错误详细异常信息
throw new ServiceException("脚本内容不规范!");
}
}
/**
* 校验并批量删除脚本信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
List<LiteflowScriptVo> liteflowScriptVos = baseMapper.selectVoList(
new LambdaQueryWrapper<LiteflowScript>().in(LiteflowScript::getId, ids));
if (isValid) {
if (CollUtil.isEmpty(liteflowScriptVos)) {
return true;
}
}
List<LiteflowFlowBus> liteflowFlowBus = liteflowScriptVos.stream()
.map(x -> {
LiteflowFlowBus flowBus = new LiteflowFlowBus();
flowBus.setLiteflowType(LiteflowType.UNLOAD_SCRIPT);
flowBus.setId(x.getScriptId());
return flowBus;
}).collect(Collectors.toList());
// 发布规则引擎事件
SpringUtils.context().publishEvent(liteflowFlowBus);
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,6 @@
<?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="org.dromara.liteflow.mapper.LiteflowChainMapper">
</mapper>

View File

@ -0,0 +1,6 @@
<?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="org.dromara.liteflow.mapper.LiteflowScriptMapper">
</mapper>

38
script/sql/liteflow.sql Normal file
View File

@ -0,0 +1,38 @@
CREATE TABLE liteflow_chain
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`application_name` varchar(32) NOT NULL COMMENT '配置环境',
`chain_name` varchar(32) NOT NULL COMMENT '编排规则ID',
`chain_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态0未激活 1激活',
`el_str` text NOT NULL COMMENT 'EL表达式',
`name_space` varchar(32) DEFAULT NULL COMMENT 'namespace决策路由很多想要判断某一组决策路由时在chain层面加入namespace参数',
`route` text COMMENT '决策路由EL',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在 2代表删除',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) engine = innodb comment = '编排规则表';
CREATE TABLE liteflow_script
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`application_name` varchar(32) NOT NULL COMMENT '配置环境',
`script_id` varchar(32) NOT NULL COMMENT '脚本ID',
`script_name` varchar(64) NOT NULL COMMENT '脚本名称',
`script_language` varchar(32) NOT NULL COMMENT '脚本语言类型groovy | qlexpress | js | python | lua | aviator | java | kotlin',
`script_type` varchar(16) NOT NULL COMMENT '脚本类型(script普通脚本节点脚本里无需返回 switch_script选择脚本节点脚本里需要返回选择的节点Id boolean_script条件脚本节点脚本里需要返回true/false for_script数量循环节点脚本里需要返回数值类型表示循环次数)',
`script_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态0未激活 1激活',
`script_data` text NOT NULL COMMENT '脚本内容',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0代表存在 2代表删除',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) engine = innodb comment = '脚本表';