From fea977730e502674f54db7bc5ce98aa1668f18a7 Mon Sep 17 00:00:00 2001 From: noear Date: Mon, 10 Oct 2022 16:10:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=20liteflow?= =?UTF-8?q?-solon-plugin=20=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- liteflow-solon-plugin/pom.xml | 39 ++++ .../annotation/LiteflowComponent.java | 25 ++ .../solon/LiteflowMonitorProperty.java | 61 +++++ .../liteflow/solon/LiteflowProperty.java | 217 ++++++++++++++++++ .../config/LiteflowMainAutoConfiguration.java | 50 ++++ .../LiteflowPropertyAutoConfiguration.java | 48 ++++ .../solon/integration/XPluginImpl.java | 50 ++++ .../liteflow/spi/solon/ResourceUtils.java | 27 +++ .../liteflow/spi/solon/SolonAware.java | 74 ++++++ .../spi/solon/SolonCmpAroundAspect.java | 42 ++++ .../spi/solon/SolonContextCmpInit.java | 21 ++ .../solon/SolonLiteflowComponentSupport.java | 30 +++ .../spi/solon/SolonPathContentParser.java | 64 ++++++ .../META-INF/liteflow-default.properties | 20 ++ .../com.yomahub.liteflow.spi.CmpAroundAspect | 2 + .../com.yomahub.liteflow.spi.ContextAware | 2 + .../com.yomahub.liteflow.spi.ContextCmpInit | 2 + ...ahub.liteflow.spi.LiteflowComponentSupport | 2 + ...com.yomahub.liteflow.spi.PathContentParser | 2 + .../solon/liteflow-solon-plugin.properties | 2 + .../src/test/java/demo/TestApp.java | 28 +++ .../src/test/java/demo/nodes/ACmp.java | 18 ++ .../src/test/java/demo/nodes/BCmp.java | 19 ++ .../src/test/java/demo/nodes/CCmp.java | 18 ++ .../src/test/resources/demo/app.yml | 3 + .../src/test/resources/demo/flow.xml | 6 + pom.xml | 2 + 27 files changed, 874 insertions(+) create mode 100644 liteflow-solon-plugin/pom.xml create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/annotation/LiteflowComponent.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowMonitorProperty.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowProperty.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowMainAutoConfiguration.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowPropertyAutoConfiguration.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/integration/XPluginImpl.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/ResourceUtils.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonAware.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonCmpAroundAspect.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonContextCmpInit.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonLiteflowComponentSupport.java create mode 100644 liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonPathContentParser.java create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.CmpAroundAspect create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextAware create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextCmpInit create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.LiteflowComponentSupport create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.PathContentParser create mode 100644 liteflow-solon-plugin/src/main/resources/META-INF/solon/liteflow-solon-plugin.properties create mode 100644 liteflow-solon-plugin/src/test/java/demo/TestApp.java create mode 100644 liteflow-solon-plugin/src/test/java/demo/nodes/ACmp.java create mode 100644 liteflow-solon-plugin/src/test/java/demo/nodes/BCmp.java create mode 100644 liteflow-solon-plugin/src/test/java/demo/nodes/CCmp.java create mode 100644 liteflow-solon-plugin/src/test/resources/demo/app.yml create mode 100644 liteflow-solon-plugin/src/test/resources/demo/flow.xml diff --git a/liteflow-solon-plugin/pom.xml b/liteflow-solon-plugin/pom.xml new file mode 100644 index 00000000..39698680 --- /dev/null +++ b/liteflow-solon-plugin/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + jar + liteflow-solon-plugin + liteflow solon plugin + + + liteflow + com.yomahub + ${revision} + ../pom.xml + + + + + + org.noear + solon + ${solon.version} + + + + com.yomahub + liteflow-core + ${revision} + + + + org.noear + solon-test + ${solon.version} + test + + + + diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/annotation/LiteflowComponent.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/annotation/LiteflowComponent.java new file mode 100644 index 00000000..ff50724f --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/annotation/LiteflowComponent.java @@ -0,0 +1,25 @@ +package com.yomahub.liteflow.annotation; + + +import java.lang.annotation.*; + +/** + * LiteFlow的组件标识注解 + * + * @author Bryan.Zhang + * @since 2.6.0 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface LiteflowComponent { + + @AliasFor("id") + String value() default ""; + + @AliasFor("value") + String id() default ""; + + String name() default ""; +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowMonitorProperty.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowMonitorProperty.java new file mode 100644 index 00000000..ba55a035 --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowMonitorProperty.java @@ -0,0 +1,61 @@ +package com.yomahub.liteflow.solon; + + +import org.noear.solon.annotation.Configuration; +import org.noear.solon.annotation.Inject; + +/** + * 监控器的基础参数类 + * + * @author Bryan.Zhang + * @author noear + * @since 2.9 + */ +@Inject("${liteflow.monitor}") +@Configuration +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; + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowProperty.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowProperty.java new file mode 100644 index 00000000..60d38e4a --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/LiteflowProperty.java @@ -0,0 +1,217 @@ +package com.yomahub.liteflow.solon; + + +import org.noear.solon.annotation.Configuration; +import org.noear.solon.annotation.Inject; + +/** + * 执行流程主要的参数类 + * + * @author Bryan.Zhang + * @author noear + * @since 2.9 + */ +@Inject("${liteflow}") +@Configuration +public class LiteflowProperty { + + //是否装配liteflow + private boolean enable; + + //流程定义资源地址 + private String ruleSource; + + //流程资源扩展数据 + private String ruleSourceExtData; + + //slot的数量 + private int slotSize; + + //FlowExecutor的execute2Future的线程数 + private int mainExecutorWorks; + + //FlowExecutor的execute2Future的自定义线程池 + private String mainExecutorClass; + + //并行线程执行器class路径 + private String threadExecutorClass; + + //异步线程最大等待描述 + private int whenMaxWaitSeconds; + + //异步线程池最大线程数 + private int whenMaxWorkers; + + //异步线程池最大队列数量 + private int whenQueueLimit; + + //是否在启动时解析规则文件 + //这个参数主要给编码式注册元数据的场景用的,结合FlowBus.addNode一起用 + private boolean parseOnStart; + + //这个属性为true,则支持多种不同的类型的配置 + //但是要注意,不能将主流程和子流程分配在不同类型配置文件中 + private boolean supportMultipleType; + + //重试次数 + private int retryCount; + + //是否打印liteflow banner + private boolean printBanner; + + // 节点执行器class全名 + private String nodeExecutorClass; + + // requestId 生成器 + private String requestIdGeneratorClass; + + //是否打印执行过程中的日志 + private boolean printExecutionLog; + + //替补组件的class路径 + private String substituteCmpClass; + + 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; + } + + public int getWhenMaxWaitSeconds() { + return whenMaxWaitSeconds; + } + + public void setWhenMaxWaitSeconds(int whenMaxWaitSeconds) { + this.whenMaxWaitSeconds = whenMaxWaitSeconds; + } + + public int getWhenMaxWorkers() { + return whenMaxWorkers; + } + + public void setWhenMaxWorkers(int whenMaxWorkers) { + this.whenMaxWorkers = whenMaxWorkers; + } + + public int getWhenQueueLimit() { + return whenQueueLimit; + } + + public void setWhenQueueLimit(int whenQueueLimit) { + this.whenQueueLimit = whenQueueLimit; + } + + public boolean isParseOnStart() { + return parseOnStart; + } + + public void setParseOnStart(boolean parseOnStart) { + this.parseOnStart = parseOnStart; + } + + public boolean isSupportMultipleType() { + return supportMultipleType; + } + + public void setSupportMultipleType(boolean supportMultipleType) { + this.supportMultipleType = supportMultipleType; + } + + public int getRetryCount() { + return retryCount; + } + + public void setRetryCount(int retryCount) { + this.retryCount = retryCount; + } + + public boolean isPrintBanner() { + return printBanner; + } + + public void setPrintBanner(boolean printBanner) { + this.printBanner = printBanner; + } + + public String getThreadExecutorClass() { + return threadExecutorClass; + } + + public void setThreadExecutorClass(String threadExecutorClass) { + this.threadExecutorClass = threadExecutorClass; + } + + 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 getSubstituteCmpClass() { + return substituteCmpClass; + } + + public void setSubstituteCmpClass(String substituteCmpClass) { + this.substituteCmpClass = substituteCmpClass; + } + + public String getRuleSourceExtData() { + return ruleSourceExtData; + } + + public void setRuleSourceExtData(String ruleSourceExtData) { + this.ruleSourceExtData = ruleSourceExtData; + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowMainAutoConfiguration.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowMainAutoConfiguration.java new file mode 100644 index 00000000..5d592c32 --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowMainAutoConfiguration.java @@ -0,0 +1,50 @@ +package com.yomahub.liteflow.solon.config; + + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.monitor.MonitorBus; +import com.yomahub.liteflow.property.LiteflowConfig; +import org.noear.solon.annotation.Bean; +import org.noear.solon.annotation.Configuration; +import org.noear.solon.annotation.Inject; + +/** + * 主要的业务装配器 + * 在这个装配器里装配了执行器,执行器初始化类,监控器 + * 这个装配前置条件是需要LiteflowConfig,LiteflowPropertyAutoConfiguration以及SpringAware + * + * @author Bryan.Zhang + * @author noear + * @since 2.9 + */ +@Configuration +public class LiteflowMainAutoConfiguration { + + @Inject("${liteflow.parse-on-start}") + boolean parseOnStart; + + @Inject("${liteflow.monitor.enable-log}") + boolean enableLog; + + //实例化FlowExecutor + @Bean + public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig) { + FlowExecutor flowExecutor = new FlowExecutor(); + flowExecutor.setLiteflowConfig(liteflowConfig); + + if (parseOnStart) { + flowExecutor.init(); + } + + return flowExecutor; + } + + @Bean + public MonitorBus monitorBus(LiteflowConfig liteflowConfig) { + if (enableLog) { + return new MonitorBus(liteflowConfig); + } else { + return null; //null 即是没创建 + } + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowPropertyAutoConfiguration.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowPropertyAutoConfiguration.java new file mode 100644 index 00000000..a8790783 --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowPropertyAutoConfiguration.java @@ -0,0 +1,48 @@ +package com.yomahub.liteflow.solon.config; + +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.solon.LiteflowMonitorProperty; +import com.yomahub.liteflow.solon.LiteflowProperty; +import org.noear.solon.annotation.Bean; +import org.noear.solon.annotation.Configuration; + +/** + * LiteflowConfig的装配类 + * + * 这个装配类主要是把监控器的配置参数类和流程配置参数类作一个合并,转换成统一的配置参数类。 + * 同时这里设置了默认的参数路径,如果在 solon 的 app.properties/yml 里没取到的话,就取默认值 + * @author Bryan.Zhang + * @author noear + * @since 2.9 + */ +@Configuration +public class LiteflowPropertyAutoConfiguration { + + @Bean + public LiteflowConfig liteflowConfig(LiteflowProperty property, LiteflowMonitorProperty liteflowMonitorProperty){ + LiteflowConfig liteflowConfig = new LiteflowConfig(); + liteflowConfig.setRuleSource(property.getRuleSource()); + liteflowConfig.setRuleSourceExtData(property.getRuleSourceExtData()); + liteflowConfig.setSlotSize(property.getSlotSize()); + liteflowConfig.setThreadExecutorClass(property.getThreadExecutorClass()); + liteflowConfig.setWhenMaxWaitSeconds(property.getWhenMaxWaitSeconds()); + liteflowConfig.setEnableLog(liteflowMonitorProperty.isEnableLog()); + liteflowConfig.setQueueLimit(liteflowMonitorProperty.getQueueLimit()); + liteflowConfig.setDelay(liteflowMonitorProperty.getDelay()); + liteflowConfig.setPeriod(liteflowMonitorProperty.getPeriod()); + liteflowConfig.setWhenMaxWorkers(property.getWhenMaxWorkers()); + liteflowConfig.setWhenQueueLimit(property.getWhenQueueLimit()); + liteflowConfig.setParseOnStart(property.isParseOnStart()); + 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.setSubstituteCmpClass(property.getSubstituteCmpClass()); + return liteflowConfig; + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/integration/XPluginImpl.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/integration/XPluginImpl.java new file mode 100644 index 00000000..44eaa502 --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/integration/XPluginImpl.java @@ -0,0 +1,50 @@ +package com.yomahub.liteflow.solon.integration; + +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.solon.LiteflowProperty; +import org.noear.solon.Solon; +import org.noear.solon.Utils; +import org.noear.solon.core.AopContext; +import org.noear.solon.core.Plugin; + +import java.util.Properties; + +/** + * @author noear + * @since 2.9 + */ +public class XPluginImpl implements Plugin { + @Override + public void start(AopContext context) { + //加载默认配置 + Properties defProps = Utils.loadProperties("META-INF/liteflow-default.properties"); + if (defProps != null && defProps.size() > 0) { + defProps.forEach((k, v) -> { + Solon.cfg().putIfAbsent(k, v); + }); + } + + //是否启用 + boolean enable = Solon.cfg().getBool("liteflow.enable", false); + + if (!enable) { + return; + } + + //订阅 NodeComponent 组件 + context.subWrapsOfType(NodeComponent.class, bw -> { + NodeComponent node1 = bw.raw(); + + if (Utils.isNotEmpty(bw.name())) { + node1.setName(bw.name()); + node1.setNodeId(bw.name()); + } + + FlowBus.addSpringScanNode(node1.getNodeId(), node1); + }); + + //扫描内部相关组件 + context.beanScan(LiteflowProperty.class); + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/ResourceUtils.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/ResourceUtils.java new file mode 100644 index 00000000..1ea0574c --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/ResourceUtils.java @@ -0,0 +1,27 @@ +package com.yomahub.liteflow.spi.solon; + + +/** + * @author noear 2022/10/10 created + */ + +public final class ResourceUtils { + public static final String CLASSPATH_URL_PREFIX = "classpath:"; + public static final String FILE_URL_PREFIX = "file:"; + public static final String JAR_URL_PREFIX = "jar:"; + public static final String WAR_URL_PREFIX = "war:"; + public static final String URL_PROTOCOL_FILE = "file"; + public static final String URL_PROTOCOL_JAR = "jar"; + public static final String URL_PROTOCOL_WAR = "war"; + public static final String URL_PROTOCOL_ZIP = "zip"; + public static final String URL_PROTOCOL_WSJAR = "wsjar"; + public static final String URL_PROTOCOL_VFSZIP = "vfszip"; + public static final String URL_PROTOCOL_VFSFILE = "vfsfile"; + public static final String URL_PROTOCOL_VFS = "vfs"; + public static final String JAR_FILE_EXTENSION = ".jar"; + public static final String JAR_URL_SEPARATOR = "!/"; + public static final String WAR_URL_SEPARATOR = "*/"; + + public static final String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; + +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonAware.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonAware.java new file mode 100644 index 00000000..da685287 --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonAware.java @@ -0,0 +1,74 @@ +package com.yomahub.liteflow.spi.solon; + +import cn.hutool.core.util.ObjectUtil; +import com.yomahub.liteflow.spi.ContextAware; +import org.noear.solon.Solon; +import org.noear.solon.core.BeanWrap; + +/** + * 基于代码形式的 Solon 上下文工具类 + * @author Bryan.Zhang + */ +public class SolonAware implements ContextAware { + + @Override + public T getBean(String name) { + try{ + return Solon.context().getBean(name); + }catch (Exception e){ + return null; + } + } + + @Override + public T getBean(Class clazz) { + try{ + return Solon.context().getBean(clazz); + }catch (Exception e){ + return null; + } + } + + private T getBean(String beanName, Class clazz) { + try{ + return Solon.context().getBean(beanName); + }catch (Exception e){ + return null; + } + } + + @Override + public T registerBean(String beanName, Class c) { + BeanWrap beanWrap = new BeanWrap(Solon.context(), c, null, beanName); + Solon.context().putWrap(beanName, beanWrap); + + return beanWrap.get(); + } + + @Override + public T registerBean(Class c) { + return registerBean(c.getName(), c); + } + + @Override + public T registerBean(String beanName, Object bean) { + BeanWrap beanWrap = new BeanWrap(Solon.context(), bean.getClass(), bean, beanName); + Solon.context().putWrap(beanName, beanWrap); + + return beanWrap.get(); + } + + @Override + public T registerOrGet(String beanName, Class clazz) { + T t = getBean(beanName, clazz); + if (ObjectUtil.isNull(t)) { + t = registerBean(beanName, clazz); + } + return t; + } + + @Override + public int priority() { + return 1; + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonCmpAroundAspect.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonCmpAroundAspect.java new file mode 100644 index 00000000..ee3571e2 --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonCmpAroundAspect.java @@ -0,0 +1,42 @@ +package com.yomahub.liteflow.spi.solon; + +import cn.hutool.core.util.ObjectUtil; +import com.yomahub.liteflow.aop.ICmpAroundAspect; +import com.yomahub.liteflow.slot.Slot; +import com.yomahub.liteflow.spi.CmpAroundAspect; +import org.noear.solon.Solon; + +/** + * Solon 环境全局组件切面实现 + * @author Bryan.Zhang + * @since 2.6.11 + */ +public class SolonCmpAroundAspect implements CmpAroundAspect { + public static ICmpAroundAspect cmpAroundAspect; + + static { + Solon.context().getBeanAsyn(ICmpAroundAspect.class, bean -> { + cmpAroundAspect = bean; + }); + } + + + @Override + public void beforeProcess(String nodeId, Slot slot) { + if (ObjectUtil.isNotNull(cmpAroundAspect)) { + cmpAroundAspect.beforeProcess(nodeId, slot); + } + } + + @Override + public void afterProcess(String nodeId, Slot slot) { + if (ObjectUtil.isNotNull(cmpAroundAspect)) { + cmpAroundAspect.afterProcess(nodeId, slot); + } + } + + @Override + public int priority() { + return 1; + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonContextCmpInit.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonContextCmpInit.java new file mode 100644 index 00000000..419204aa --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonContextCmpInit.java @@ -0,0 +1,21 @@ +package com.yomahub.liteflow.spi.solon; + +import com.yomahub.liteflow.spi.ContextCmpInit; + + +/** + * Solon 环境容器上下文组件初始化实现 + * @author Bryan.Zhang + * @since 2.6.11 + */ +public class SolonContextCmpInit implements ContextCmpInit { + @Override + public void initCmp() { + //todo: 转到 FlowBus.addSpringScanNode 不需要了 + } + + @Override + public int priority() { + return 1; + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonLiteflowComponentSupport.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonLiteflowComponentSupport.java new file mode 100644 index 00000000..ce5bd32a --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonLiteflowComponentSupport.java @@ -0,0 +1,30 @@ +package com.yomahub.liteflow.spi.solon; + +import cn.hutool.core.util.ObjectUtil; +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.spi.LiteflowComponentSupport; + +/** + * Solon 环境 LiteflowComponent 注解的处理器 + * @author Bryan.Zhang + * @since 2.6.11 + */ +public class SolonLiteflowComponentSupport implements LiteflowComponentSupport { + @Override + public String getCmpName(NodeComponent nodeComponent) { + //判断NodeComponent是否是标识了@LiteflowComponent的标注 + //如果标注了,那么要从中取到name字段 + LiteflowComponent liteflowComponent = nodeComponent.getClass().getAnnotation(LiteflowComponent.class); + if (ObjectUtil.isNotNull(liteflowComponent)) { + return liteflowComponent.name(); + }else{ + return null; + } + } + + @Override + public int priority() { + return 1; + } +} \ No newline at end of file diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonPathContentParser.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonPathContentParser.java new file mode 100644 index 00000000..b2774d0f --- /dev/null +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/spi/solon/SolonPathContentParser.java @@ -0,0 +1,64 @@ +package com.yomahub.liteflow.spi.solon; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.exception.ConfigErrorException; +import com.yomahub.liteflow.spi.PathContentParser; +import org.noear.solon.Utils; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SolonPathContentParser implements PathContentParser { + @Override + public List parseContent(List pathList) throws Exception { + if(CollectionUtil.isEmpty(pathList)){ + throw new ConfigErrorException("rule source must not be null"); + } + + List allResource = new ArrayList<>(); + for (String path : pathList) { + //如果 path 是绝对路径且这个文件存在时,我们认为这是一个本地文件路径,而并非classpath路径 + if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) { + allResource.add(new File(path).toURI().toURL()); + } else { + if (path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) { + path = path.substring(ResourceUtils.CLASSPATH_URL_PREFIX.length()); + } + + allResource.add(Utils.getResource(path)); + } + } + + //如果有多个资源,检查资源都是同一个类型,如果出现不同类型的配置,则抛出错误提示 + Set fileTypeSet = new HashSet<>(); + allResource.forEach(resource -> fileTypeSet.add(FileUtil.extName(resource.getPath()))); + if (fileTypeSet.size() != 1) { + throw new ConfigErrorException("config error,please use the same type of configuration"); + } + + //转换成内容List + List contentList = new ArrayList<>(); + for (URL resource : allResource) { + String content = IoUtil.read(resource.openStream(), CharsetUtil.CHARSET_UTF_8); + if (StrUtil.isNotBlank(content)){ + contentList.add(content); + } + } + + return contentList; + } + + @Override + public int priority() { + return 1; + } +} diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties b/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties new file mode 100644 index 00000000..35a41afd --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties @@ -0,0 +1,20 @@ +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.thread-executor-class=com.yomahub.liteflow.thread.LiteFlowDefaultWhenExecutorBuilder +liteflow.when-max-wait-seconds=15 +liteflow.when-max-workers=16 +liteflow.when-queue-limit=512 +liteflow.parse-on-start=true +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.substitute-cmp-class= +liteflow.monitor.enable-log=false +liteflow.monitor.queue-limit=200 +liteflow.monitor.delay=300000 +liteflow.monitor.period=300000 diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.CmpAroundAspect b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.CmpAroundAspect new file mode 100644 index 00000000..61966fd1 --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.CmpAroundAspect @@ -0,0 +1,2 @@ +# Spring 的实现 +com.yomahub.liteflow.spi.solon.SolonCmpAroundAspect \ No newline at end of file diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextAware b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextAware new file mode 100644 index 00000000..29a2157b --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextAware @@ -0,0 +1,2 @@ +# Spring 的实现 +com.yomahub.liteflow.spi.solon.SolonAware \ No newline at end of file diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextCmpInit b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextCmpInit new file mode 100644 index 00000000..d757b065 --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.ContextCmpInit @@ -0,0 +1,2 @@ +# Spring 的实现 +com.yomahub.liteflow.spi.solon.SolonContextCmpInit \ No newline at end of file diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.LiteflowComponentSupport b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.LiteflowComponentSupport new file mode 100644 index 00000000..c5b3f660 --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.LiteflowComponentSupport @@ -0,0 +1,2 @@ +# Spring 的实现 +com.yomahub.liteflow.spi.solon.SolonLiteflowComponentSupport \ No newline at end of file diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.PathContentParser b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.PathContentParser new file mode 100644 index 00000000..691eeb9c --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/services/com.yomahub.liteflow.spi.PathContentParser @@ -0,0 +1,2 @@ +# Spring 的实现 +com.yomahub.liteflow.spi.solon.SolonPathContentParser \ No newline at end of file diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/solon/liteflow-solon-plugin.properties b/liteflow-solon-plugin/src/main/resources/META-INF/solon/liteflow-solon-plugin.properties new file mode 100644 index 00000000..80f690e5 --- /dev/null +++ b/liteflow-solon-plugin/src/main/resources/META-INF/solon/liteflow-solon-plugin.properties @@ -0,0 +1,2 @@ +solon.plugin=com.yomahub.liteflow.solon.integration.XPluginImpl +solon.plugin.priority=1 \ No newline at end of file diff --git a/liteflow-solon-plugin/src/test/java/demo/TestApp.java b/liteflow-solon-plugin/src/test/java/demo/TestApp.java new file mode 100644 index 00000000..55e92634 --- /dev/null +++ b/liteflow-solon-plugin/src/test/java/demo/TestApp.java @@ -0,0 +1,28 @@ +package demo; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.noear.snack.ONode; +import org.noear.solon.annotation.Inject; +import org.noear.solon.test.SolonJUnit4ClassRunner; +import org.noear.solon.test.SolonTest; +import org.noear.solon.test.annotation.TestPropertySource; + +/** + * @author noear 2022/9/21 created + */ + +@RunWith(SolonJUnit4ClassRunner.class) +@TestPropertySource("classpath:demo/app.yml") +public class TestApp { + @Inject + FlowExecutor flowExecutor; + + @Test + public void test() throws Exception{ + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + System.out.println(ONode.stringify(response)); + } +} diff --git a/liteflow-solon-plugin/src/test/java/demo/nodes/ACmp.java b/liteflow-solon-plugin/src/test/java/demo/nodes/ACmp.java new file mode 100644 index 00000000..96072bc3 --- /dev/null +++ b/liteflow-solon-plugin/src/test/java/demo/nodes/ACmp.java @@ -0,0 +1,18 @@ +package demo.nodes; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import org.noear.solon.annotation.Component; + +/** + * @author noear 2022/9/21 created + */ +@Component("a") +public class ACmp extends NodeComponent { + + @Override + public void process() { + //do your business + System.out.println(this.getClass().getName()); + } +} diff --git a/liteflow-solon-plugin/src/test/java/demo/nodes/BCmp.java b/liteflow-solon-plugin/src/test/java/demo/nodes/BCmp.java new file mode 100644 index 00000000..6fa0e4c4 --- /dev/null +++ b/liteflow-solon-plugin/src/test/java/demo/nodes/BCmp.java @@ -0,0 +1,19 @@ +package demo.nodes; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import org.noear.solon.annotation.Component; + +/** + * @author noear 2022/9/21 created + */ +@Component("b") +public class BCmp extends NodeComponent { + + @Override + public void process() { + //do your business + System.out.println(this.getClass().getName()); + } +} + diff --git a/liteflow-solon-plugin/src/test/java/demo/nodes/CCmp.java b/liteflow-solon-plugin/src/test/java/demo/nodes/CCmp.java new file mode 100644 index 00000000..21d4cdf9 --- /dev/null +++ b/liteflow-solon-plugin/src/test/java/demo/nodes/CCmp.java @@ -0,0 +1,18 @@ +package demo.nodes; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import org.noear.solon.annotation.Component; + +/** + * @author noear 2022/9/21 created + */ +@Component("c") +public class CCmp extends NodeComponent { + + @Override + public void process() { + //do your business + System.out.println(this.getClass().getName()); + } +} diff --git a/liteflow-solon-plugin/src/test/resources/demo/app.yml b/liteflow-solon-plugin/src/test/resources/demo/app.yml new file mode 100644 index 00000000..c261a253 --- /dev/null +++ b/liteflow-solon-plugin/src/test/resources/demo/app.yml @@ -0,0 +1,3 @@ + + +liteflow.rule-source: "demo/flow.xml" \ No newline at end of file diff --git a/liteflow-solon-plugin/src/test/resources/demo/flow.xml b/liteflow-solon-plugin/src/test/resources/demo/flow.xml new file mode 100644 index 00000000..049210cf --- /dev/null +++ b/liteflow-solon-plugin/src/test/resources/demo/flow.xml @@ -0,0 +1,6 @@ + + + + THEN(a, b, c); + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 22ab26d9..d712efb6 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,7 @@ 1.11.13 1.8.13 1.2.3 + 1.10.6 @@ -339,6 +340,7 @@ liteflow-rule-plugin liteflow-spring-boot-starter liteflow-spring + liteflow-solon-plugin liteflow-testcase-el