feat(springboot4): 新增 liteflow-spring-boot4-starter

适配 Spring Boot 4 / Spring 7 / JDK 17+ 的自动装配 starter:
- 提供 LiteflowProperty / LiteflowMonitorProperty 配置绑定
- LiteflowMainAutoConfiguration / LiteflowPropertyAutoConfiguration 通过 AutoConfiguration.imports 注册
- LiteflowExecutorInit 负责启动期初始化 FlowExecutor
- 根 pom 引入 springboot4.version=4.0.6,并将 release profile 拆分为 release-on-8 / release-on-17,新模块在 JDK 17+ profile 与 release-on-17 profile 中接入

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
everywhere.z
2026-04-30 23:55:09 +08:00
parent ea3a8315e4
commit 2e92eb506d
11 changed files with 1130 additions and 62 deletions

View File

@@ -0,0 +1,114 @@
<?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>
<packaging>jar</packaging>
<artifactId>liteflow-spring-boot4-starter</artifactId>
<name>${project.artifactId}</name>
<description>liteflow springboot 4 starter</description>
<parent>
<artifactId>liteflow</artifactId>
<groupId>com.yomahub</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<skipTests>false</skipTests>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot4.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.32</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>7.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>7.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>7.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>7.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>7.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>7.0.7</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${springboot4.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot4.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${springboot4.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${skipTests}</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,24 @@
package com.yomahub.liteflow.springboot4;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.FlowBus;
import org.springframework.beans.factory.SmartInitializingSingleton;
/**
* 执行器初始化类 主要用于在启动时执行执行器的初始化方法,避免在运行执行器时第一次初始化而耗费时间
*
* @author Bryan.Zhang
*/
public class LiteflowExecutorInit implements SmartInitializingSingleton {
private final FlowExecutor flowExecutor;
public LiteflowExecutorInit(FlowExecutor flowExecutor) {
this.flowExecutor = flowExecutor;
}
@Override
public void afterSingletonsInstantiated() {
flowExecutor.init(true);
FlowBus.needInit();
}
}

View File

@@ -0,0 +1,57 @@
package com.yomahub.liteflow.springboot4;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 监控器的基础参数类
*
* @author Bryan.Zhang
*/
@ConfigurationProperties(prefix = "liteflow.monitor", ignoreUnknownFields = true)
public class LiteflowMonitorProperty {
// 是否打印监控日志
private boolean enableLog;
// 监控队列存储的最大数量
private int queueLimit;
// 延迟多少毫秒打印
private long delay;
// 每隔多少毫秒打印
private long period;
public boolean isEnableLog() {
return enableLog;
}
public void setEnableLog(boolean enableLog) {
this.enableLog = enableLog;
}
public int getQueueLimit() {
return queueLimit;
}
public void setQueueLimit(int queueLimit) {
this.queueLimit = queueLimit;
}
public long getDelay() {
return delay;
}
public void setDelay(long delay) {
this.delay = delay;
}
public long getPeriod() {
return period;
}
public void setPeriod(long period) {
this.period = period;
}
}

View File

@@ -0,0 +1,393 @@
package com.yomahub.liteflow.springboot4;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.enums.ParseModeEnum;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 执行流程主要的参数类
*
* @author Bryan.Zhang
* @author jason
*/
@ConfigurationProperties(prefix = "liteflow", ignoreUnknownFields = true)
public class LiteflowProperty {
// 是否装配liteflow
private boolean enable;
// 流程定义资源地址
private String ruleSource;
// 流程资源扩展数据String格式
private String ruleSourceExtData;
// 流程资源扩展数据Map格式
private Map<String, String> ruleSourceExtDataMap;
// slot的数量
private int slotSize;
// FlowExecutor的execute2Future的线程数
private int mainExecutorWorks;
// FlowExecutor的execute2Future的自定义线程池
private String mainExecutorClass;
// 异步线程最大等待描述
@Deprecated
private int whenMaxWaitSeconds;
private int whenMaxWaitTime;
private TimeUnit whenMaxWaitTimeUnit;
// 异步线程池是否隔离
private boolean whenThreadPoolIsolate;
// 解析模式,一共有三种,具体看其定义
private ParseModeEnum parseMode;
// 这个属性为true则支持多种不同的类型的配置
// 但是要注意,不能将主流程和子流程分配在不同类型配置文件中
private boolean supportMultipleType;
// 重试次数
@Deprecated
private int retryCount;
// 是否打印liteflow banner
private boolean printBanner;
// 节点执行器class全名
private String nodeExecutorClass;
// requestId 生成器
private String requestIdGeneratorClass;
// 是否打印执行过程中的日志
private boolean printExecutionLog;
// 规则文件/脚本文件变更监听
private boolean enableMonitorFile;
// 是否启用组件降级
private boolean fallbackCmpEnable;
//是否快速加载规则如果快速加载规则意味着不用copyOnWrite机制了
private boolean fastLoad;
//是否检查节点存在
private boolean checkNodeExists;
//脚本特殊设置选项
private Map<String, String> scriptSetting;
//全局线程池所用class路径(when+异步循环)
private String globalThreadPoolExecutorClass;
//全局线程池最大线程数(when+异步循环)
private Integer globalThreadPoolSize;
//全局线程池最大队列数(when+异步循环)
private Integer globalThreadPoolQueueSize;
//是否启用节点实例ID
private boolean enableNodeInstanceId;
// 是否开启虚拟线程(只在jdk21环境下奏效)
private boolean enableVirtualThread;
// 规则缓存配置
@NestedConfigurationProperty
private ChainCacheProperty chainCache;
// Agent配置
@NestedConfigurationProperty
private com.yomahub.liteflow.property.agent.AgentConfig agent;
public static class ChainCacheProperty {
// 是否启用规则缓存
private Boolean enabled;
// chain缓存容量
private Integer capacity;
public Boolean isEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public Integer getCapacity() {
return capacity;
}
public void setCapacity(Integer capacity) {
this.capacity = capacity;
}
}
public boolean isEnableMonitorFile() {
return enableMonitorFile;
}
public void setEnableMonitorFile(boolean enableMonitorFile) {
this.enableMonitorFile = enableMonitorFile;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getRuleSource() {
return ruleSource;
}
public void setRuleSource(String ruleSource) {
this.ruleSource = ruleSource;
}
public int getSlotSize() {
return slotSize;
}
public void setSlotSize(int slotSize) {
this.slotSize = slotSize;
}
@Deprecated
public int getWhenMaxWaitSeconds() {
return whenMaxWaitSeconds;
}
@Deprecated
public void setWhenMaxWaitSeconds(int whenMaxWaitSeconds) {
this.whenMaxWaitSeconds = whenMaxWaitSeconds;
}
public ParseModeEnum getParseMode() {
return parseMode;
}
public void setParseMode(ParseModeEnum parseMode) {
this.parseMode = parseMode;
}
public boolean isSupportMultipleType() {
return supportMultipleType;
}
public void setSupportMultipleType(boolean supportMultipleType) {
this.supportMultipleType = supportMultipleType;
}
@Deprecated
public int getRetryCount() {
return retryCount;
}
@Deprecated
public void setRetryCount(int retryCount) {
this.retryCount = retryCount;
}
public boolean isPrintBanner() {
return printBanner;
}
public void setPrintBanner(boolean printBanner) {
this.printBanner = printBanner;
}
public String getNodeExecutorClass() {
return nodeExecutorClass;
}
public void setNodeExecutorClass(String nodeExecutorClass) {
this.nodeExecutorClass = nodeExecutorClass;
}
public int getMainExecutorWorks() {
return mainExecutorWorks;
}
public void setMainExecutorWorks(int mainExecutorWorks) {
this.mainExecutorWorks = mainExecutorWorks;
}
public String getMainExecutorClass() {
return mainExecutorClass;
}
public void setMainExecutorClass(String mainExecutorClass) {
this.mainExecutorClass = mainExecutorClass;
}
public boolean isPrintExecutionLog() {
return printExecutionLog;
}
public void setPrintExecutionLog(boolean printExecutionLog) {
this.printExecutionLog = printExecutionLog;
}
public String getRequestIdGeneratorClass() {
return requestIdGeneratorClass;
}
public void setRequestIdGeneratorClass(String requestIdGeneratorClass) {
this.requestIdGeneratorClass = requestIdGeneratorClass;
}
public String getRuleSourceExtData() {
return ruleSourceExtData;
}
public void setRuleSourceExtData(String ruleSourceExtData) {
this.ruleSourceExtData = ruleSourceExtData;
}
public Map<String, String> getRuleSourceExtDataMap() {
return ruleSourceExtDataMap;
}
public void setRuleSourceExtDataMap(Map<String, String> ruleSourceExtDataMap) {
this.ruleSourceExtDataMap = ruleSourceExtDataMap;
}
public int getWhenMaxWaitTime() {
return whenMaxWaitTime;
}
public void setWhenMaxWaitTime(int whenMaxWaitTime) {
this.whenMaxWaitTime = whenMaxWaitTime;
}
public TimeUnit getWhenMaxWaitTimeUnit() {
return whenMaxWaitTimeUnit;
}
public void setWhenMaxWaitTimeUnit(TimeUnit whenMaxWaitTimeUnit) {
this.whenMaxWaitTimeUnit = whenMaxWaitTimeUnit;
}
public boolean isFallbackCmpEnable() {
return fallbackCmpEnable;
}
public void setFallbackCmpEnable(boolean fallbackCmpEnable) {
this.fallbackCmpEnable = fallbackCmpEnable;
}
public boolean isWhenThreadPoolIsolate() {
return whenThreadPoolIsolate;
}
public void setWhenThreadPoolIsolate(boolean whenThreadPoolIsolate) {
this.whenThreadPoolIsolate = whenThreadPoolIsolate;
}
public boolean isFastLoad() {
return fastLoad;
}
public void setFastLoad(boolean fastLoad) {
this.fastLoad = fastLoad;
}
public boolean isCheckNodeExists() {
return checkNodeExists;
}
public void setCheckNodeExists(boolean checkNodeExists) {
this.checkNodeExists = checkNodeExists;
}
public Map<String, String> getScriptSetting() {
return scriptSetting;
}
public void setScriptSetting(Map<String, String> scriptSetting) {
this.scriptSetting = scriptSetting;
}
public Integer getGlobalThreadPoolSize() {
if (ObjectUtil.isNull(globalThreadPoolSize)) {
return 16;
} else {
return globalThreadPoolSize;
}
}
public void setGlobalThreadPoolSize(Integer globalThreadPoolSize) {
this.globalThreadPoolSize = globalThreadPoolSize;
}
public Integer getGlobalThreadPoolQueueSize() {
if (ObjectUtil.isNull(globalThreadPoolQueueSize)) {
return 512;
} else {
return globalThreadPoolQueueSize;
}
}
public void setGlobalThreadPoolQueueSize(Integer globalThreadPoolQueueSize) {
this.globalThreadPoolQueueSize = globalThreadPoolQueueSize;
}
public String getGlobalThreadPoolExecutorClass() {
if (StrUtil.isBlank(globalThreadPoolExecutorClass)) {
return "com.yomahub.liteflow.thread.LiteFlowDefaultGlobalExecutorBuilder";
} else {
return globalThreadPoolExecutorClass;
}
}
public void setGlobalThreadPoolExecutorClass(String globalThreadPoolExecutorClass) {
this.globalThreadPoolExecutorClass = globalThreadPoolExecutorClass;
}
public boolean isEnableNodeInstanceId() {
return enableNodeInstanceId;
}
public void setEnableNodeInstanceId(boolean enableNodeInstanceId) {
this.enableNodeInstanceId = enableNodeInstanceId;
}
public ChainCacheProperty getChainCache() {
return chainCache;
}
public void setChainCache(ChainCacheProperty chainCache) {
this.chainCache = chainCache;
}
public boolean isEnableVirtualThread() {
return enableVirtualThread;
}
public void setEnableVirtualThread(boolean enableVirtualThread) {
this.enableVirtualThread = enableVirtualThread;
}
public com.yomahub.liteflow.property.agent.AgentConfig getAgent() {
return agent;
}
public void setAgent(com.yomahub.liteflow.property.agent.AgentConfig agent) {
this.agent = agent;
}
}

View File

@@ -0,0 +1,82 @@
package com.yomahub.liteflow.springboot4.config;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.monitor.MonitorBus;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.spring.SpringAware;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.spring.DeclBeanDefinition;
import com.yomahub.liteflow.springboot4.LiteflowExecutorInit;
import com.yomahub.liteflow.spring.LiteflowSpiInit;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
/**
* 主要的业务装配器 在这个装配器里装配了执行器,执行器初始化类,监控器
* 这个装配前置条件是需要LiteflowConfigLiteflowPropertyAutoConfiguration以及SpringAware
*
* @author Bryan.Zhang
*/
@AutoConfiguration
@AutoConfigureAfter({ LiteflowPropertyAutoConfiguration.class })
@ConditionalOnBean(LiteflowConfig.class)
@ConditionalOnProperty(prefix = "liteflow", name = "enable", havingValue = "true")
@Import(SpringAware.class)
public class LiteflowMainAutoConfiguration {
@Bean
public DeclBeanDefinition declBeanDefinition(){
return new DeclBeanDefinition();
}
// 实例化ComponentScanner
// 多加一个SpringAware的意义是确保在执行这个的时候SpringAware这个bean已经被初始化
@Bean
public ComponentScanner componentScanner(LiteflowConfig liteflowConfig, SpringAware springAware) {
return new ComponentScanner(liteflowConfig);
}
// 实例化FlowExecutor
// 多加一个SpringAware的意义是确保在执行这个的时候SpringAware这个bean已经被初始化
@Bean
@ConditionalOnMissingBean
public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig, SpringAware springAware) {
FlowExecutor flowExecutor = new FlowExecutor();
flowExecutor.setLiteflowConfig(liteflowConfig);
return flowExecutor;
}
// FlowExecutor的初始化工作和实例化分开来
// 这里写2个几乎一样的是因为无论是在PARSE_ALL_ON_START或者PARSE_ONE_ON_FIRST_EXEC模式下都需要初始化工作
// 换句话说,这两个只可能被执行一个
@Bean
@ConditionalOnProperty(prefix = "liteflow", name = "parse-mode", havingValue = "PARSE_ALL_ON_START")
public LiteflowExecutorInit liteflowExecutorInit1(FlowExecutor flowExecutor) {
return new LiteflowExecutorInit(flowExecutor);
}
@Bean
@ConditionalOnProperty(prefix = "liteflow", name = "parse-mode", havingValue = "PARSE_ONE_ON_FIRST_EXEC")
public LiteflowExecutorInit liteflowExecutorInit2(FlowExecutor flowExecutor) {
return new LiteflowExecutorInit(flowExecutor);
}
// 实例化MonitorBus
// 多加一个SpringAware的意义是确保在执行这个的时候SpringAware这个bean已经被初始化
@Bean("monitorBus")
@ConditionalOnProperty(prefix = "liteflow", name = "monitor.enable-log", havingValue = "true")
public MonitorBus monitorBus(LiteflowConfig liteflowConfig, SpringAware springAware) {
return new MonitorBus(liteflowConfig);
}
// 初始化 SPI ,避免多线程场景下类加载器不同导致的加载不到 SPI 实现类
@Bean
public LiteflowSpiInit liteflowSpiInit() {
return new LiteflowSpiInit();
}
}

View File

@@ -0,0 +1,63 @@
package com.yomahub.liteflow.springboot4.config;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.springboot4.LiteflowMonitorProperty;
import com.yomahub.liteflow.springboot4.LiteflowProperty;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
/**
* LiteflowConfig的装配类 这个装配类主要是把监控器的配置参数类和流程配置参数类作一个合并,转换成统一的配置参数类。
* 同时这里设置了默认的参数路径如果在springboot的application.properties/yml里没取到的话就取默认值
*
* @author Bryan.Zhang
* @author jason
*/
@AutoConfiguration
@EnableConfigurationProperties({ LiteflowProperty.class, LiteflowMonitorProperty.class })
@PropertySource(name = "Liteflow Default Properties", value = "classpath:/META-INF/liteflow-default.properties")
public class LiteflowPropertyAutoConfiguration {
@Bean
public LiteflowConfig liteflowConfig(LiteflowProperty property, LiteflowMonitorProperty liteflowMonitorProperty) {
LiteflowConfig liteflowConfig = new LiteflowConfig();
liteflowConfig.setRuleSource(property.getRuleSource());
liteflowConfig.setRuleSourceExtData(property.getRuleSourceExtData());
liteflowConfig.setRuleSourceExtDataMap(property.getRuleSourceExtDataMap());
liteflowConfig.setSlotSize(property.getSlotSize());
liteflowConfig.setWhenMaxWaitSeconds(property.getWhenMaxWaitSeconds());
liteflowConfig.setWhenMaxWaitTime(property.getWhenMaxWaitTime());
liteflowConfig.setWhenMaxWaitTimeUnit(property.getWhenMaxWaitTimeUnit());
liteflowConfig.setWhenThreadPoolIsolate(property.isWhenThreadPoolIsolate());
liteflowConfig.setParseMode(property.getParseMode());
liteflowConfig.setEnable(property.isEnable());
liteflowConfig.setSupportMultipleType(property.isSupportMultipleType());
liteflowConfig.setRetryCount(property.getRetryCount());
liteflowConfig.setPrintBanner(property.isPrintBanner());
liteflowConfig.setNodeExecutorClass(property.getNodeExecutorClass());
liteflowConfig.setRequestIdGeneratorClass(property.getRequestIdGeneratorClass());
liteflowConfig.setMainExecutorWorks(property.getMainExecutorWorks());
liteflowConfig.setMainExecutorClass(property.getMainExecutorClass());
liteflowConfig.setPrintExecutionLog(property.isPrintExecutionLog());
liteflowConfig.setEnableMonitorFile(property.isEnableMonitorFile());
liteflowConfig.setFallbackCmpEnable(property.isFallbackCmpEnable());
liteflowConfig.setFastLoad(property.isFastLoad());
liteflowConfig.setEnableLog(liteflowMonitorProperty.isEnableLog());
liteflowConfig.setQueueLimit(liteflowMonitorProperty.getQueueLimit());
liteflowConfig.setDelay(liteflowMonitorProperty.getDelay());
liteflowConfig.setPeriod(liteflowMonitorProperty.getPeriod());
liteflowConfig.setScriptSetting(property.getScriptSetting());
liteflowConfig.setGlobalThreadPoolExecutorClass(property.getGlobalThreadPoolExecutorClass());
liteflowConfig.setGlobalThreadPoolQueueSize(property.getGlobalThreadPoolQueueSize());
liteflowConfig.setGlobalThreadPoolSize(property.getGlobalThreadPoolSize());
liteflowConfig.setEnableNodeInstanceId(property.isEnableNodeInstanceId());
liteflowConfig.setEnableVirtualThread(property.isEnableVirtualThread());
liteflowConfig.setChainCacheEnabled(property.getChainCache().isEnabled());
liteflowConfig.setChainCacheCapacity(property.getChainCache().getCapacity());
liteflowConfig.setAgent(property.getAgent());
return liteflowConfig;
}
}

View File

@@ -0,0 +1,232 @@
{
"properties": [
{
"name": "liteflow.rule-source-ext-data",
"type": "java.lang.String",
"description": "rule source extended data.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty"
},
{
"name": "liteflow.rule-source-ext-data-map",
"type": "java.util.Map",
"description": "rule source extended data map.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty"
},
{
"name": "liteflow.request-id-generator-class",
"type": "java.lang.String",
"description": "Custom requestId builder.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "com.yomahub.liteflow.flow.id.DefaultRequestIdGenerator"
},
{
"name": "liteflow.rule-source",
"type": "java.lang.String",
"description": "Location of the flow rule source.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "config/flow.xml"
},
{
"name": "liteflow.enable",
"type": "java.lang.Boolean",
"description": "Whether to turn on liteflow.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": true
},
{
"name": "liteflow.print-banner",
"type": "java.lang.Boolean",
"description": "Whether to print liteflow banner.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": true
},
{
"name": "liteflow.slot-size",
"type": "java.lang.Integer",
"description": "Set concurrent data slot size.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 1024
},
{
"name": "liteflow.main-executor-works",
"type": "java.lang.Integer",
"description": "Max thread count for main executor,only for FlowExecutor.execute2Future.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 64
},
{
"name": "liteflow.main-executor-class",
"type": "java.lang.String",
"description": "Custom thread pool implement for main executor.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "com.yomahub.liteflow.thread.LiteFlowDefaultMainExecutorBuilder"
},
{
"name": "liteflow.when-max-wait-seconds",
"type": "java.lang.Integer",
"description": "Set the async thread max wait seconds on \" when \" mode.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 0
},
{
"name": "liteflow.when-max-wait-time",
"type": "java.lang.Integer",
"description": "Set the async thread max wait time on \" when \" mode.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 15000
},
{
"name": "liteflow.when-max-wait-time-unit",
"type": "java.util.concurrent.TimeUnit",
"description": "Set the async thread max wait time unit on \" when \" mode.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "MILLISECONDS"
},
{
"name": "liteflow.when-thread-pool-isolate",
"type": "java.lang.Boolean",
"description": "set whether the asynchronous thread pool is isolated.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": false
},
{
"name": "liteflow.parse-mode",
"type": "com.yomahub.liteflow.enums.ParseModeEnum",
"description": "Set parse mode at startup.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "PARSE_ALL_ON_START"
},
{
"name": "liteflow.retry-count",
"type": "java.lang.Integer",
"description": "Number of component retries.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 0
},
{
"name": "liteflow.support-multiple-type",
"type": "java.lang.Boolean",
"description": "Whether to support multiple types of configuration.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": false
},
{
"name": "liteflow.node-executor-class",
"type": "java.lang.String",
"description": "Executor class of node.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "com.yomahub.liteflow.flow.executor.DefaultNodeExecutor"
},
{
"name": "liteflow.print-execution-log",
"type": "java.lang.Boolean",
"description": "Whether to print logs during execution.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": true
},
{
"name": "liteflow.fallback-cmp-enable",
"type": "java.lang.Boolean",
"description": "Whether to enable component fallback.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": false
},
{
"name": "liteflow.fast-load",
"type": "java.lang.Boolean",
"description": "Whether to enable fast load mode.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": false
},
{
"name": "liteflow.monitor.enable-log",
"type": "java.lang.Boolean",
"description": "Enable monitor log.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowMonitorProperty",
"defaultValue": false
},
{
"name": "liteflow.monitor.queue-limit",
"type": "java.lang.Integer",
"description": "Set monitor queue size.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowMonitorProperty",
"defaultValue": 200
},
{
"name": "liteflow.monitor.delay",
"type": "java.lang.Long",
"description": "Set delay time to print monitor log.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowMonitorProperty",
"defaultValue": 300000
},
{
"name": "liteflow.monitor.period",
"type": "java.lang.Long",
"description": "Set period time to print monitor log.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowMonitorProperty",
"defaultValue": 300000
},
{
"name": "liteflow.enable-monitor-file",
"type": "java.lang.Boolean",
"description": "Set file change monitoring.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowMonitorProperty",
"defaultValue": false
},
{
"name": "liteflow.global-thread-pool-size",
"type": "java.lang.Integer",
"description": "Set the global chain thread pool worker max-size.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 16
},
{
"name": "liteflow.global-thread-pool-queue-size",
"type": "java.lang.Integer",
"description": "Set the global chain thread pool queue max-size.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 512
},
{
"name": "liteflow.global-thread-pool-executor-class",
"type": "java.lang.String",
"description": "Custom the global chain thread pool implement for global chain executor.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": "com.yomahub.liteflow.thread.LiteFlowDefaultGlobalExecutorBuilder"
},
{
"name": "liteflow.script-setting",
"type": "java.util.Map",
"description": "Script special settings.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty"
},
{
"name": "liteflow.enable-node-instance-id",
"type": "java.lang.Boolean",
"description": "Whether to enable node instance id.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": false
},
{
"name": "liteflow.enable-virtual-thread",
"type": "java.lang.Boolean",
"description": "Whether to enable virtual threads(Only in jdk21).",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": true
},
{
"name": "liteflow.chain-cache.enabled",
"type": "java.lang.Boolean",
"description": "Whether to enable chain cache.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": false
},
{
"name": "liteflow.chain-cache.capacity",
"type": "java.lang.Integer",
"description": "Set chain cache capacity.",
"sourceType": "com.yomahub.liteflow.springboot4.LiteflowProperty",
"defaultValue": 10000
}
]
}

View File

@@ -0,0 +1,31 @@
liteflow.enable=true
liteflow.print-banner=true
liteflow.slot-size=1024
liteflow.main-executor-works=64
liteflow.main-executor-class=com.yomahub.liteflow.thread.LiteFlowDefaultMainExecutorBuilder
liteflow.request-id-generator-class=com.yomahub.liteflow.flow.id.DefaultRequestIdGenerator
liteflow.when-max-wait-time=15000
liteflow.when-max-wait-time-unit=MILLISECONDS
liteflow.when-thread-pool-isolate=false
liteflow.parse-mode=PARSE_ALL_ON_START
liteflow.retry-count=0
liteflow.support-multiple-type=false
liteflow.node-executor-class=com.yomahub.liteflow.flow.executor.DefaultNodeExecutor
liteflow.print-execution-log=true
liteflow.fallback-cmp-enable=false
liteflow.fast-load=false
liteflow.check-node-exists=true
liteflow.monitor.enable-log=false
liteflow.monitor.queue-limit=200
liteflow.monitor.delay=300000
liteflow.monitor.period=300000
liteflow.enable-monitor-file=false
liteflow.global-thread-pool-size=64
liteflow.global-thread-pool-queue-size=512
liteflow.global-thread-pool-executor-class=com.yomahub.liteflow.thread.LiteFlowDefaultGlobalExecutorBuilder
liteflow.enable-node-instance-id=false
liteflow.enable-virtual-thread=true
liteflow.chain-cache.enabled=false
liteflow.chain-cache.capacity=10000

View File

@@ -0,0 +1,2 @@
com.yomahub.liteflow.springboot4.config.LiteflowPropertyAutoConfiguration
com.yomahub.liteflow.springboot4.config.LiteflowMainAutoConfiguration

View File

@@ -0,0 +1,67 @@
package com.yomahub.liteflow.springboot4.config;
import com.yomahub.liteflow.enums.ParseModeEnum;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.springboot4.LiteflowProperty;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
class LiteflowBoot4AutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(LiteflowPropertyAutoConfiguration.class));
@Test
void bindLiteflowConfigWithSpringBoot4AutoConfiguration() {
contextRunner
.withPropertyValues(
"liteflow.slot-size=16",
"liteflow.parse-mode=PARSE_ONE_ON_FIRST_EXEC",
"liteflow.monitor.enable-log=true",
"liteflow.chain-cache.enabled=true",
"liteflow.chain-cache.capacity=32")
.run(context -> {
assertThat(context).hasSingleBean(LiteflowProperty.class);
assertThat(context).hasSingleBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = context.getBean(LiteflowConfig.class);
assertThat(liteflowConfig.getSlotSize()).isEqualTo(16);
assertThat(liteflowConfig.getParseMode()).isEqualTo(ParseModeEnum.PARSE_ONE_ON_FIRST_EXEC);
assertThat(liteflowConfig.getEnableLog()).isTrue();
assertThat(liteflowConfig.getChainCacheEnabled()).isTrue();
assertThat(liteflowConfig.getChainCacheCapacity()).isEqualTo(32);
});
}
@Test
void publishBoot4AutoConfigurationImportsOnly() throws Exception {
Path classesPath = classesPath();
Path importsPath = classesPath.resolve("META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports");
assertThat(importsPath).exists();
assertThat(Files.readAllLines(importsPath)).containsExactly(
"com.yomahub.liteflow.springboot4.config.LiteflowPropertyAutoConfiguration",
"com.yomahub.liteflow.springboot4.config.LiteflowMainAutoConfiguration");
assertThat(classesPath.resolve("META-INF/spring.factories")).doesNotExist();
}
private Path classesPath() throws Exception {
URI uri = LiteflowPropertyAutoConfiguration.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI();
Path path = Paths.get(uri);
if (Files.isRegularFile(path)) {
return path.getParent();
}
return path;
}
}

127
pom.xml
View File

@@ -45,6 +45,7 @@
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<springboot.version>2.6.8</springboot.version>
<springboot4.version>4.0.6</springboot4.version>
<spring.version>5.3.20</spring.version>
<org.slf4j.version>1.7.32</org.slf4j.version>
<jackson.version>2.16.0</jackson.version>
@@ -530,68 +531,6 @@
</activation>
</profile>
<profile>
<id>release-main</id>
<modules>
<module>liteflow-core</module>
<module>liteflow-script-plugin</module>
<module>liteflow-rule-plugin</module>
<module>liteflow-spring-boot-starter</module>
<module>liteflow-spring</module>
<module>liteflow-solon-plugin</module>
<module>liteflow-el-builder</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release-react-agent</id>
<modules>
<module>liteflow-react-agent</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
<!-- ReAct Agent 模块:需要 Java 21+agentscope-java 要求JDK 版本满足时自动激活 -->
<profile>
<id>compile-17+</id>
@@ -603,6 +542,7 @@
<module>liteflow-script-plugin</module>
<module>liteflow-rule-plugin</module>
<module>liteflow-spring-boot-starter</module>
<module>liteflow-spring-boot4-starter</module>
<module>liteflow-spring</module>
<module>liteflow-solon-plugin</module>
<module>liteflow-testcase-el</module>
@@ -611,5 +551,68 @@
<module>liteflow-react-agent</module>
</modules>
</profile>
<profile>
<id>release-on-8</id>
<modules>
<module>liteflow-core</module>
<module>liteflow-script-plugin</module>
<module>liteflow-rule-plugin</module>
<module>liteflow-spring-boot-starter</module>
<module>liteflow-spring</module>
<module>liteflow-solon-plugin</module>
<module>liteflow-el-builder</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release-on-17</id>
<modules>
<module>liteflow-react-agent</module>
<module>liteflow-spring-boot4-starter</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>