diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/pom.xml b/liteflow-rule-plugin/liteflow-rule-nacos/pom.xml new file mode 100644 index 000000000..b8a1a96d6 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/pom.xml @@ -0,0 +1,29 @@ + + + + liteflow-rule-plugin + com.yomahub + ${revision} + ../pom.xml + + 4.0.0 + + liteflow-rule-nacos + + + + com.yomahub + liteflow-core + ${revision} + true + + + + com.alibaba.nacos + nacos-client + 1.2.1 + + + \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/NacosXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/NacosXmlELParser.java new file mode 100644 index 000000000..76e6f4504 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/NacosXmlELParser.java @@ -0,0 +1,66 @@ +package com.yomahub.liteflow.parser.nacos; + +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; +import com.yomahub.liteflow.parser.nacos.exception.NacosException; +import com.yomahub.liteflow.parser.nacos.util.NacosParserHelper; +import com.yomahub.liteflow.parser.nacos.vo.NacosParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.util.JsonUtil; + +import java.util.function.Consumer; + +/** + * Nacos 解析器实现,只支持EL形式的XML,不支持其他的形式 + * @author mll + * @since 2.9.0 + */ +public class NacosXmlELParser extends ClassXmlFlowELParser { + + private final NacosParserHelper helper; + + public NacosXmlELParser() { + Consumer parseConsumer = t -> { + try { + parse(t); + } catch (Exception e) { + throw new RuntimeException(e); + } + }; + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + + if (StrUtil.isBlank(liteflowConfig.getRuleSourceExtData())){ + throw new NacosException("rule-source-ext-data for nacos is empty"); + } + + try{ + NacosParserVO nacosParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), NacosParserVO.class); + assert nacosParserVO != null; + if (StrUtil.isBlank(nacosParserVO.getServerAddr())){ + nacosParserVO.setServerAddr("127.0.0.1:8848"); + } + if (StrUtil.isBlank(nacosParserVO.getDataId())){ + nacosParserVO.setDataId("LiteFLow"); + } + if (StrUtil.isBlank(nacosParserVO.getGroup())){ + nacosParserVO.setGroup("LiteFLowConfig"); + } + helper = new NacosParserHelper(nacosParserVO, parseConsumer); + }catch (Exception e){ + throw new NacosException(e.getMessage()); + } + } + + @Override + public String parseCustom() { + try{ + String content = helper.getContent(); + helper.checkContent(content); + helper.listener(); + return content; + }catch (Exception e){ + throw new NacosException(e.getMessage()); + } + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/exception/NacosException.java b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/exception/NacosException.java new file mode 100644 index 000000000..7b59de8ba --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/exception/NacosException.java @@ -0,0 +1,23 @@ + +package com.yomahub.liteflow.parser.nacos.exception; + +public class NacosException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** 异常信息 */ + private String message; + + public NacosException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/util/NacosParserHelper.java b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/util/NacosParserHelper.java new file mode 100644 index 000000000..dd58cdfc7 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/util/NacosParserHelper.java @@ -0,0 +1,94 @@ +package com.yomahub.liteflow.parser.nacos.util; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.config.listener.Listener; +import com.yomahub.liteflow.exception.ParseException; +import com.yomahub.liteflow.parser.nacos.exception.NacosException; +import com.yomahub.liteflow.parser.nacos.vo.NacosParserVO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.MessageFormat; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +/** + * Nacos client for http api + * OpenAPI + * @author mll + * @since 2.9.0 + */ +public class NacosParserHelper { + private static final Logger LOG = LoggerFactory.getLogger(NacosParserHelper.class); + + private final NacosParserVO nacosParserVO; + private final Consumer parseConsumer; + + private static final ConcurrentHashMap CONFIG_MAP = new ConcurrentHashMap<>(1); + + private final ConfigService configService; + + static { + CONFIG_MAP.put("Content",""); + } + + public NacosParserHelper(NacosParserVO nacosParserVO, Consumer parseConsumer) { + this.nacosParserVO = nacosParserVO; + this.parseConsumer = parseConsumer; + try{ + Properties properties = new Properties(); + properties.put(PropertyKeyConst.SERVER_ADDR, nacosParserVO.getServerAddr()); + this.configService = NacosFactory.createConfigService(properties); + CONFIG_MAP.put("Content",configService.getConfig(nacosParserVO.getDataId(), nacosParserVO.getGroup(), 3000L)); + }catch (Exception e){ + throw new NacosException(e.getMessage()); + } + } + + public String getContent(){ + try{ + return CONFIG_MAP.get("Content"); + }catch (Exception e){ + throw new NacosException(e.getMessage()); + } + } + + /** + * 检查 content 是否合法 + */ + public void checkContent(String content) { + if (StrUtil.isBlank(content)) { + String error = MessageFormat.format("the node[{0}] value is empty", nacosParserVO.toString()); + throw new ParseException(error); + } + } + + /** + * 监听 nacos 数据变化 + */ + public void listener() { + try { + this.configService.addListener(nacosParserVO.getDataId(), nacosParserVO.getGroup(), new Listener() { + @Override + public void receiveConfigInfo(String configInfo) { + LOG.info("stating load flow config.... {} " , configInfo); + CONFIG_MAP.put("Content",configInfo); + parseConsumer.accept(configInfo); + } + @Override + public Executor getExecutor() { + return null; + } + }); + }catch (Exception ex){ + LOG.error("listener Exception {} " , ex.getMessage()); + throw new NacosException(ex.getMessage()); + } + } + +} diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/vo/NacosParserVO.java b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/vo/NacosParserVO.java new file mode 100644 index 000000000..9a3be5305 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/nacos/vo/NacosParserVO.java @@ -0,0 +1,69 @@ +package com.yomahub.liteflow.parser.nacos.vo; + +/** + * 用于解析 RuleSourceExtData 的vo类,用于nacos模式中 + * @author mll + * @since 2.9.0 + */ +public class NacosParserVO { + private String serverAddr; + private String namespace; + private String dataId; + private String group; + private String username; + private String password; + + public String getServerAddr() { + return serverAddr; + } + + public void setServerAddr(String serverAddr) { + this.serverAddr = serverAddr; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getDataId() { + return dataId; + } + + public void setDataId(String dataId) { + this.dataId = dataId; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "NacosParserVO{" + "serverAddr='" + serverAddr + '\'' + ", namespace='" + namespace + '\'' + ", dataId='" + dataId + '\'' + ", group='" + group + '\'' + + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/spi/nacos/NacosParserClassNameSpi.java b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/spi/nacos/NacosParserClassNameSpi.java new file mode 100644 index 000000000..95a25ed5b --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/java/com/yomahub/liteflow/parser/spi/nacos/NacosParserClassNameSpi.java @@ -0,0 +1,17 @@ +package com.yomahub.liteflow.parser.spi.nacos; + +import com.yomahub.liteflow.parser.nacos.NacosXmlELParser; +import com.yomahub.liteflow.parser.spi.ParserClassNameSpi; + +/** + * Nacos 解析器SPI实现 + * @author mll + * @since 2.9.0 + */ +public class NacosParserClassNameSpi implements ParserClassNameSpi { + + @Override + public String getSpiClassName() { + return NacosXmlELParser.class.getName(); + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-nacos/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi new file mode 100644 index 000000000..37a3dea64 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-nacos/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi @@ -0,0 +1 @@ +com.yomahub.liteflow.parser.spi.nacos.NacosParserClassNameSpi \ No newline at end of file diff --git a/liteflow-rule-plugin/pom.xml b/liteflow-rule-plugin/pom.xml index 4e1601b44..d02f63722 100644 --- a/liteflow-rule-plugin/pom.xml +++ b/liteflow-rule-plugin/pom.xml @@ -12,6 +12,7 @@ pom liteflow-rule-zk + liteflow-rule-nacos liteflow-rule-plugin diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/pom.xml new file mode 100644 index 000000000..7cae8c461 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/pom.xml @@ -0,0 +1,63 @@ + + + + liteflow-testcase-el + com.yomahub + ${revision} + ../pom.xml + + 4.0.0 + + liteflow-testcase-el-nacos-springboot + + + + com.yomahub + liteflow-spring-boot-starter + ${revision} + + + + org.springframework.boot + spring-boot-starter-test + + + org.aspectj + aspectjweaver + test + + + org.apache.curator + curator-test + test + + + + com.yomahub + liteflow-rule-nacos + ${revision} + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${springboot.version} + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java new file mode 100644 index 000000000..64886670f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java @@ -0,0 +1,20 @@ +package com.yomahub.liteflow.test; + +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.thread.ExecutorHelper; +import org.junit.AfterClass; + +public class BaseTest { + + @AfterClass + public static void cleanScanCache(){ + ComponentScanner.cleanCache(); + FlowBus.cleanCache(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); + LiteflowConfigGetter.clean(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/NacosWithXmlELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/NacosWithXmlELSpringbootTest.java new file mode 100644 index 000000000..fbc905ea8 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/NacosWithXmlELSpringbootTest.java @@ -0,0 +1,44 @@ +package com.yomahub.liteflow.test.nacos; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +/** + * springboot环境下的nacos配置源功能测试 + * nacos存储数据的格式为xml文件 + * @author mll + * @since 2.9.0 + */ +@RunWith(SpringRunner.class) +@TestPropertySource(value = "classpath:/nacos/application-xml.properties") +@SpringBootTest(classes = NacosWithXmlELSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.nacos.cmp"}) +public class NacosWithXmlELSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + @Test + public void testNacosWithXml() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assert.assertTrue(response.isSuccess()); + Assert.assertEquals("a==>b==>c", response.getExecuteStepStr()); + for (int i = 0 ; i < 10; i ++){ + Thread.sleep(10000L); + response = flowExecutor.execute2Resp("chain1", "arg"); + System.out.println(" i " + response.getExecuteStepStr()); + } + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/ACmp.java new file mode 100644 index 000000000..6e6300a7f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/ACmp.java @@ -0,0 +1,20 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.nacos.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("a") +public class ACmp extends NodeComponent { + + @Override + public void process() { + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/BCmp.java new file mode 100644 index 000000000..a4b339770 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/BCmp.java @@ -0,0 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.nacos.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("b") +public class BCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("BCmp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/CCmp.java new file mode 100644 index 000000000..0c9de012b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/java/com/yomahub/liteflow/test/nacos/cmp/CCmp.java @@ -0,0 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.nacos.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("c") +public class CCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("CCmp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/resources/nacos/application-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/resources/nacos/application-xml.properties new file mode 100644 index 000000000..a41924a0d --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nacos-springboot/src/test/resources/nacos/application-xml.properties @@ -0,0 +1,3 @@ +#liteflow.rule-source-ext-data={"serverAddr":"192.168.10.147:8848"} +#liteflow.rule-source-ext-data={"serverAddr":"192.168.10.147:8848","dataId":"LiteFlow","group":"LITE_FLOW_GROUP"} +liteflow.rule-source-ext-data={"serverAddr":"192.168.10.147:8848","dataId":"LiteFlow","group":"LITE_FLOW_GROUP","namespace":"","username":"","password":""} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-zk-springboot/src/test/resources/zookeeper/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-zk-springboot/src/test/resources/zookeeper/flow.xml deleted file mode 100644 index 049210cf4..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-zk-springboot/src/test/resources/zookeeper/flow.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - THEN(a, b, c); - - \ No newline at end of file diff --git a/liteflow-testcase-el/pom.xml b/liteflow-testcase-el/pom.xml index ad5434740..89bbc870d 100644 --- a/liteflow-testcase-el/pom.xml +++ b/liteflow-testcase-el/pom.xml @@ -22,5 +22,6 @@ liteflow-testcase-el-script-groovy-springboot liteflow-testcase-el-script-qlexpress-springboot liteflow-testcase-el-zk-springboot + liteflow-testcase-el-nacos-springboot \ No newline at end of file