瀏覽代碼

!219 修复了ApolloParse可能存在的空指针问题和命名规范问题
Merge pull request !219 from 韩华锋/fix_null_problem_230914

铂赛东 1 年之前
父節點
當前提交
13ef344281

+ 5 - 5
liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowInitHook.java

@@ -14,20 +14,20 @@ import java.util.function.BooleanSupplier;
  */
 public class FlowInitHook {
 
-	private static final List<BooleanSupplier> supplierList = new ArrayList<>();
+	private static final List<BooleanSupplier> SUPPLIER_LIST = new ArrayList<>();
 
 	public static void executeHook() {
-		if (CollUtil.isNotEmpty(supplierList)) {
-			supplierList.forEach(BooleanSupplier::getAsBoolean);
+		if (CollUtil.isNotEmpty(SUPPLIER_LIST)) {
+			SUPPLIER_LIST.forEach(BooleanSupplier::getAsBoolean);
 		}
 	}
 
 	public static void addHook(BooleanSupplier hookSupplier) {
-		supplierList.add(hookSupplier);
+		SUPPLIER_LIST.add(hookSupplier);
 	}
 
 	public static void cleanHook() {
-		supplierList.clear();
+		SUPPLIER_LIST.clear();
 	}
 
 }

+ 211 - 204
liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java

@@ -25,215 +25,222 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import static com.ctrip.framework.apollo.enums.PropertyChangeType.DELETED;
+
 /**
  * @author zhanghua
  * @since 2.9.5
  */
 public class ApolloParseHelper {
 
-	private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class);
-
-	private final String CHAIN_XML_PATTERN = "<chain name=\"{}\">{}</chain>";
-
-	private final String NODE_XML_PATTERN = "<nodes>{}</nodes>";
-
-	private final String NODE_ITEM_XML_PATTERN = "<node id=\"{}\" name=\"{}\" type=\"{}\"><![CDATA[{}]]></node>";
-
-	private final String XML_PATTERN = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow>{}{}</flow>";
-
-	private final ApolloParserConfigVO apolloParserConfigVO;
-
-	private Config chainConfig;
-
-	private Config scriptConfig;
-
-	public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) {
-		this.apolloParserConfigVO = apolloParserConfigVO;
-
-		try {
-			try {
-				// 这里本身对于程序运行来说没有什么意义,拿到的永远是null
-				// 其实config对象也没有注入到spring容器中
-				// 这里这样写的目的是为了单测中的mockito,当有@MockBean的时候,这里就能拿到了
-				this.chainConfig = ContextAwareHolder.loadContextAware().getBean("chainConfig");
-				this.scriptConfig = ContextAwareHolder.loadContextAware().getBean("scriptConfig");
-			}
-			catch (Exception ignored) {
-			}
-
-			if (ObjectUtil.isNull(chainConfig)) {
-				chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace());
-				String scriptNamespace;
-				// scriptConfig is optional
-				if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) {
-					scriptConfig = ConfigService.getConfig(scriptNamespace);
-				}
-			}
-		}
-		catch (Exception e) {
-			throw new ApolloException(e.getMessage());
-		}
-	}
-
-	public String getContent() {
-
-		try {
-			// 1. handle chain
-			Set<String> propertyNames = chainConfig.getPropertyNames();
-			if (CollectionUtil.isEmpty(propertyNames)) {
-				throw new ApolloException(StrUtil.format("There are no chains in namespace : {}",
-						apolloParserConfigVO.getChainNamespace()));
-			}
-			List<String> chainItemContentList = propertyNames.stream()
-				.map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY)))
-				.collect(Collectors.toList());
-			// merge all chain content
-			String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY);
-
-			// 2. handle script if needed
-			String scriptAllContent = StrUtil.EMPTY;
-			Set<String> scriptNamespaces;
-			if (Objects.nonNull(scriptConfig)
-					&& CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) {
-
-				List<String> scriptItemContentList = scriptNamespaces.stream()
-					.map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY)))
-					.filter(Objects::nonNull)
-					.map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(),
-							item.getScript()))
-					.collect(Collectors.toList());
-
-				scriptAllContent = StrUtil.format(NODE_XML_PATTERN,
-						CollUtil.join(scriptItemContentList, StrUtil.EMPTY));
-			}
-
-			return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent);
-		}
-		catch (Exception e) {
-			throw new ApolloException(e.getMessage());
-		}
-	}
-
-	/**
-	 * listen apollo config change
-	 */
-	public void listenApollo() {
-
-		// chain
-		chainConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
-			ConfigChange configChange = changeEvent.getChange(changeKey);
-			String newValue = configChange.getNewValue();
-			PropertyChangeType changeType = configChange.getChangeType();
-			switch (changeType) {
-				case ADDED:
-				case MODIFIED:
-					LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey,
-							newValue);
-					LiteFlowChainELBuilder.createChain().setChainId(changeKey).setEL(newValue).build();
-					break;
-				case DELETED:
-					LOG.info("starting reload flow config... delete key={}", changeKey);
-					FlowBus.removeChain(changeKey);
-
-			}
-		}));
-
-		if (StrUtil.isNotBlank(apolloParserConfigVO.getScriptNamespace())) {
-			scriptConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
-				ConfigChange configChange = changeEvent.getChange(changeKey);
-				String newValue = configChange.getNewValue();
-
-				PropertyChangeType changeType = configChange.getChangeType();
-
-				NodeSimpleVO nodeSimpleVO;
-				switch (changeType) {
-					case ADDED:
-					case MODIFIED:
-						LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey,
-								newValue);
-						nodeSimpleVO = convert(changeKey, newValue);
-						LiteFlowNodeBuilder.createScriptNode()
-							.setId(nodeSimpleVO.getNodeId())
-							.setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
-							.setName(nodeSimpleVO.getName())
-							.setScript(nodeSimpleVO.getScript())
-							.build();
-						break;
-					case DELETED:
-						LOG.info("starting reload flow config... delete key={}", changeKey);
-						nodeSimpleVO = convert(changeKey, null);
-						FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId());
-				}
-			}));
-		}
-	}
-
-	private NodeSimpleVO convert(String key, String value) {
-		// 不需要去理解这串正则,就是一个匹配冒号的
-		// 一定得是a:b,或是a:b:c...这种完整类型的字符串的
-		List<String> matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", key);
-		if (CollUtil.isEmpty(matchItemList)) {
-			return null;
-		}
-
-		NodeSimpleVO nodeSimpleVO = new NodeSimpleVO();
-		if (matchItemList.size() > 1) {
-			nodeSimpleVO.setNodeId(matchItemList.get(0));
-			nodeSimpleVO.setType(matchItemList.get(1));
-		}
-
-		if (matchItemList.size() > 2) {
-			nodeSimpleVO.setName(matchItemList.get(2));
-		}
-
-		// set script
-		nodeSimpleVO.setScript(value);
-
-		return nodeSimpleVO;
-	}
-
-	private static class NodeSimpleVO {
-
-		private String nodeId;
-
-		private String type;
-
-		private String name = StrUtil.EMPTY;
-
-		private String script;
-
-		public String getNodeId() {
-			return nodeId;
-		}
-
-		public void setNodeId(String nodeId) {
-			this.nodeId = nodeId;
-		}
-
-		public String getType() {
-			return type;
-		}
-
-		public void setType(String type) {
-			this.type = type;
-		}
-
-		public String getName() {
-			return name;
-		}
-
-		public void setName(String name) {
-			this.name = name;
-		}
-
-		public String getScript() {
-			return script;
-		}
-
-		public void setScript(String script) {
-			this.script = script;
-		}
-
-	}
+    private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class);
+
+    private final String CHAIN_XML_PATTERN = "<chain name=\"{}\">{}</chain>";
+
+    private final String NODE_XML_PATTERN = "<nodes>{}</nodes>";
+
+    private final String NODE_ITEM_XML_PATTERN = "<node id=\"{}\" name=\"{}\" type=\"{}\"><![CDATA[{}]]></node>";
+
+    private final String XML_PATTERN = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow>{}{}</flow>";
+
+    private final ApolloParserConfigVO apolloParserConfigVO;
+
+    private Config chainConfig;
+
+    private Config scriptConfig;
+
+    public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) {
+        this.apolloParserConfigVO = apolloParserConfigVO;
+
+        try {
+            try {
+                // 这里本身对于程序运行来说没有什么意义,拿到的永远是null
+                // 其实config对象也没有注入到spring容器中
+                // 这里这样写的目的是为了单测中的mockito,当有@MockBean的时候,这里就能拿到了
+                this.chainConfig = ContextAwareHolder.loadContextAware().getBean("chainConfig");
+                this.scriptConfig = ContextAwareHolder.loadContextAware().getBean("scriptConfig");
+            } catch (Exception ignored) {
+            }
+
+            if (ObjectUtil.isNull(chainConfig)) {
+                chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace());
+                String scriptNamespace;
+                // scriptConfig is optional
+                if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) {
+                    scriptConfig = ConfigService.getConfig(scriptNamespace);
+                }
+            }
+        } catch (Exception e) {
+            throw new ApolloException(e.getMessage());
+        }
+    }
+
+    public String getContent() {
+
+        try {
+            // 1. handle chain
+            Set<String> propertyNames = chainConfig.getPropertyNames();
+            if (CollectionUtil.isEmpty(propertyNames)) {
+                throw new ApolloException(StrUtil.format("There are no chains in namespace : {}",
+                        apolloParserConfigVO.getChainNamespace()));
+            }
+            List<String> chainItemContentList = propertyNames.stream()
+                    .map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY)))
+                    .collect(Collectors.toList());
+            // merge all chain content
+            String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY);
+
+            // 2. handle script if needed
+            String scriptAllContent = StrUtil.EMPTY;
+            Set<String> scriptNamespaces;
+            if (Objects.nonNull(scriptConfig)
+                    && CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) {
+
+                List<String> scriptItemContentList = scriptNamespaces.stream()
+                        .map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY)))
+                        .filter(Objects::nonNull)
+                        .map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(),
+                                item.getScript()))
+                        .collect(Collectors.toList());
+
+                scriptAllContent = StrUtil.format(NODE_XML_PATTERN,
+                        CollUtil.join(scriptItemContentList, StrUtil.EMPTY));
+            }
+
+            return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent);
+        } catch (Exception e) {
+            throw new ApolloException(e.getMessage());
+        }
+    }
+
+    /**
+     * listen apollo config change
+     */
+    public void listenApollo() {
+        // chain
+        chainConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
+            ConfigChange configChange = changeEvent.getChange(changeKey);
+            String newValue = configChange.getNewValue();
+            PropertyChangeType changeType = configChange.getChangeType();
+            switch (changeType) {
+                case ADDED:
+                case MODIFIED:
+                    LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey,
+                            newValue);
+                    LiteFlowChainELBuilder.createChain().setChainId(changeKey).setEL(newValue).build();
+                    break;
+                case DELETED:
+                    LOG.info("starting reload flow config... delete key={}", changeKey);
+                    FlowBus.removeChain(changeKey);
+                    break;
+                default:
+            }
+        }));
+
+        if (StrUtil.isNotBlank(apolloParserConfigVO.getScriptNamespace())) {
+            scriptConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
+                ConfigChange configChange = changeEvent.getChange(changeKey);
+                String newValue = configChange.getNewValue();
+
+                PropertyChangeType changeType = configChange.getChangeType();
+                if (DELETED.equals(changeType)) {
+                    newValue = null;
+                }
+                NodeSimpleVO nodeSimpleVO = convert(changeKey, newValue);
+                if (Objects.isNull(nodeSimpleVO)) {
+                    // key不符合规范的时候,直接忽略
+                    LOG.error("key={} is not a valid node config, ignore it", changeKey);
+                    return;
+                }
+                switch (changeType) {
+                    case ADDED:
+                    case MODIFIED:
+                        LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey,
+                                newValue);
+
+                        LiteFlowNodeBuilder.createScriptNode()
+                                .setId(nodeSimpleVO.getNodeId())
+                                .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
+                                .setName(nodeSimpleVO.getName())
+                                .setScript(nodeSimpleVO.getScript())
+                                .build();
+                        break;
+                    case DELETED:
+                        LOG.info("starting reload flow config... delete key={}", changeKey);
+                        FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId());
+                        break;
+                    default:
+                }
+            }));
+        }
+    }
+
+    private NodeSimpleVO convert(String key, String value) {
+        // 不需要去理解这串正则,就是一个匹配冒号的
+        // 一定得是a:b,或是a:b:c...这种完整类型的字符串的
+        List<String> matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", key);
+        if (CollUtil.isEmpty(matchItemList)) {
+            return null;
+        }
+
+        NodeSimpleVO nodeSimpleVO = new NodeSimpleVO();
+        if (matchItemList.size() > 1) {
+            nodeSimpleVO.setNodeId(matchItemList.get(0));
+            nodeSimpleVO.setType(matchItemList.get(1));
+        }
+
+        if (matchItemList.size() > 2) {
+            nodeSimpleVO.setName(matchItemList.get(2));
+        }
+
+        // set script
+        nodeSimpleVO.setScript(value);
+
+        return nodeSimpleVO;
+    }
+
+    private static class NodeSimpleVO {
+
+        private String nodeId;
+
+        private String type;
+
+        private String name = StrUtil.EMPTY;
+
+        private String script;
+
+        public String getNodeId() {
+            return nodeId;
+        }
+
+        public void setNodeId(String nodeId) {
+            this.nodeId = nodeId;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getScript() {
+            return script;
+        }
+
+        public void setScript(String script) {
+            this.script = script;
+        }
+
+    }
 
 }