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