mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 20:22:07 +08:00
【fix】修复ApolloParseHelper.java中调用convert后,可能会出现空指针的问题
【fix】FlowInitHook.java文件中,常量命小写,不符合常用规范,改为了大写
This commit is contained in:
@@ -14,20 +14,20 @@ import java.util.function.BooleanSupplier;
|
|||||||
*/
|
*/
|
||||||
public class FlowInitHook {
|
public class FlowInitHook {
|
||||||
|
|
||||||
private static final List<BooleanSupplier> supplierList = new ArrayList<>();
|
private static final List<BooleanSupplier> SUPPLIER_LIST = new ArrayList<>();
|
||||||
|
|
||||||
public static void executeHook() {
|
public static void executeHook() {
|
||||||
if (CollUtil.isNotEmpty(supplierList)) {
|
if (CollUtil.isNotEmpty(SUPPLIER_LIST)) {
|
||||||
supplierList.forEach(BooleanSupplier::getAsBoolean);
|
SUPPLIER_LIST.forEach(BooleanSupplier::getAsBoolean);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addHook(BooleanSupplier hookSupplier) {
|
public static void addHook(BooleanSupplier hookSupplier) {
|
||||||
supplierList.add(hookSupplier);
|
SUPPLIER_LIST.add(hookSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void cleanHook() {
|
public static void cleanHook() {
|
||||||
supplierList.clear();
|
SUPPLIER_LIST.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,215 +24,222 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.ctrip.framework.apollo.enums.PropertyChangeType.DELETED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author zhanghua
|
* @author zhanghua
|
||||||
* @since 2.9.5
|
* @since 2.9.5
|
||||||
*/
|
*/
|
||||||
public class ApolloParseHelper {
|
public class ApolloParseHelper {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class);
|
||||||
|
|
||||||
private final String CHAIN_XML_PATTERN = "<chain name=\"{}\">{}</chain>";
|
private final String CHAIN_XML_PATTERN = "<chain name=\"{}\">{}</chain>";
|
||||||
|
|
||||||
private final String NODE_XML_PATTERN = "<nodes>{}</nodes>";
|
private final String NODE_XML_PATTERN = "<nodes>{}</nodes>";
|
||||||
|
|
||||||
private final String NODE_ITEM_XML_PATTERN = "<node id=\"{}\" name=\"{}\" type=\"{}\"><![CDATA[{}]]></node>";
|
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 String XML_PATTERN = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow>{}{}</flow>";
|
||||||
|
|
||||||
private final ApolloParserConfigVO apolloParserConfigVO;
|
private final ApolloParserConfigVO apolloParserConfigVO;
|
||||||
|
|
||||||
private Config chainConfig;
|
private Config chainConfig;
|
||||||
|
|
||||||
private Config scriptConfig;
|
private Config scriptConfig;
|
||||||
|
|
||||||
public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) {
|
public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) {
|
||||||
this.apolloParserConfigVO = apolloParserConfigVO;
|
this.apolloParserConfigVO = apolloParserConfigVO;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
// 这里本身对于程序运行来说没有什么意义,拿到的永远是null
|
// 这里本身对于程序运行来说没有什么意义,拿到的永远是null
|
||||||
// 其实config对象也没有注入到spring容器中
|
// 其实config对象也没有注入到spring容器中
|
||||||
// 这里这样写的目的是为了单测中的mockito,当有@MockBean的时候,这里就能拿到了
|
// 这里这样写的目的是为了单测中的mockito,当有@MockBean的时候,这里就能拿到了
|
||||||
this.chainConfig = ContextAwareHolder.loadContextAware().getBean("chainConfig");
|
this.chainConfig = ContextAwareHolder.loadContextAware().getBean("chainConfig");
|
||||||
this.scriptConfig = ContextAwareHolder.loadContextAware().getBean("scriptConfig");
|
this.scriptConfig = ContextAwareHolder.loadContextAware().getBean("scriptConfig");
|
||||||
}
|
} catch (Exception ignored) {
|
||||||
catch (Exception ignored) {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtil.isNull(chainConfig)) {
|
if (ObjectUtil.isNull(chainConfig)) {
|
||||||
chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace());
|
chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace());
|
||||||
String scriptNamespace;
|
String scriptNamespace;
|
||||||
// scriptConfig is optional
|
// scriptConfig is optional
|
||||||
if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) {
|
if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) {
|
||||||
scriptConfig = ConfigService.getConfig(scriptNamespace);
|
scriptConfig = ConfigService.getConfig(scriptNamespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
throw new ApolloException(e.getMessage());
|
||||||
throw new ApolloException(e.getMessage());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public String getContent() {
|
public String getContent() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. handle chain
|
// 1. handle chain
|
||||||
Set<String> propertyNames = chainConfig.getPropertyNames();
|
Set<String> propertyNames = chainConfig.getPropertyNames();
|
||||||
if (CollectionUtil.isEmpty(propertyNames)) {
|
if (CollectionUtil.isEmpty(propertyNames)) {
|
||||||
throw new ApolloException(StrUtil.format("There are no chains in namespace : {}",
|
throw new ApolloException(StrUtil.format("There are no chains in namespace : {}",
|
||||||
apolloParserConfigVO.getChainNamespace()));
|
apolloParserConfigVO.getChainNamespace()));
|
||||||
}
|
}
|
||||||
List<String> chainItemContentList = propertyNames.stream()
|
List<String> chainItemContentList = propertyNames.stream()
|
||||||
.map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY)))
|
.map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY)))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
// merge all chain content
|
// merge all chain content
|
||||||
String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY);
|
String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY);
|
||||||
|
|
||||||
// 2. handle script if needed
|
// 2. handle script if needed
|
||||||
String scriptAllContent = StrUtil.EMPTY;
|
String scriptAllContent = StrUtil.EMPTY;
|
||||||
Set<String> scriptNamespaces;
|
Set<String> scriptNamespaces;
|
||||||
if (Objects.nonNull(scriptConfig)
|
if (Objects.nonNull(scriptConfig)
|
||||||
&& CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) {
|
&& CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) {
|
||||||
|
|
||||||
List<String> scriptItemContentList = scriptNamespaces.stream()
|
List<String> scriptItemContentList = scriptNamespaces.stream()
|
||||||
.map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY)))
|
.map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY)))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(),
|
.map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(),
|
||||||
item.getScript()))
|
item.getScript()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
scriptAllContent = StrUtil.format(NODE_XML_PATTERN,
|
scriptAllContent = StrUtil.format(NODE_XML_PATTERN,
|
||||||
CollUtil.join(scriptItemContentList, StrUtil.EMPTY));
|
CollUtil.join(scriptItemContentList, StrUtil.EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent);
|
return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
throw new ApolloException(e.getMessage());
|
||||||
throw new ApolloException(e.getMessage());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* listen apollo config change
|
* listen apollo config change
|
||||||
*/
|
*/
|
||||||
public void listenApollo() {
|
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:
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
// chain
|
if (StrUtil.isNotBlank(apolloParserConfigVO.getScriptNamespace())) {
|
||||||
chainConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
|
scriptConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
|
||||||
ConfigChange configChange = changeEvent.getChange(changeKey);
|
ConfigChange configChange = changeEvent.getChange(changeKey);
|
||||||
String newValue = configChange.getNewValue();
|
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);
|
|
||||||
|
|
||||||
}
|
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);
|
||||||
|
|
||||||
if (StrUtil.isNotBlank(apolloParserConfigVO.getScriptNamespace())) {
|
LiteFlowNodeBuilder.createScriptNode()
|
||||||
scriptConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> {
|
.setId(nodeSimpleVO.getNodeId())
|
||||||
ConfigChange configChange = changeEvent.getChange(changeKey);
|
.setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
|
||||||
String newValue = configChange.getNewValue();
|
.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:
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PropertyChangeType changeType = configChange.getChangeType();
|
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;
|
NodeSimpleVO nodeSimpleVO = new NodeSimpleVO();
|
||||||
switch (changeType) {
|
if (matchItemList.size() > 1) {
|
||||||
case ADDED:
|
nodeSimpleVO.setNodeId(matchItemList.get(0));
|
||||||
case MODIFIED:
|
nodeSimpleVO.setType(matchItemList.get(1));
|
||||||
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) {
|
if (matchItemList.size() > 2) {
|
||||||
// 不需要去理解这串正则,就是一个匹配冒号的
|
nodeSimpleVO.setName(matchItemList.get(2));
|
||||||
// 一定得是a:b,或是a:b:c...这种完整类型的字符串的
|
}
|
||||||
List<String> matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", key);
|
|
||||||
if (CollUtil.isEmpty(matchItemList)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeSimpleVO nodeSimpleVO = new NodeSimpleVO();
|
// set script
|
||||||
if (matchItemList.size() > 1) {
|
nodeSimpleVO.setScript(value);
|
||||||
nodeSimpleVO.setNodeId(matchItemList.get(0));
|
|
||||||
nodeSimpleVO.setType(matchItemList.get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchItemList.size() > 2) {
|
return nodeSimpleVO;
|
||||||
nodeSimpleVO.setName(matchItemList.get(2));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// set script
|
private static class NodeSimpleVO {
|
||||||
nodeSimpleVO.setScript(value);
|
|
||||||
|
|
||||||
return nodeSimpleVO;
|
private String nodeId;
|
||||||
}
|
|
||||||
|
|
||||||
private static class NodeSimpleVO {
|
private String type;
|
||||||
|
|
||||||
private String nodeId;
|
private String name = StrUtil.EMPTY;
|
||||||
|
|
||||||
private String type;
|
private String script;
|
||||||
|
|
||||||
private String name = StrUtil.EMPTY;
|
public String getNodeId() {
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
private String script;
|
public void setNodeId(String nodeId) {
|
||||||
|
this.nodeId = nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getNodeId() {
|
public String getType() {
|
||||||
return nodeId;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeId(String nodeId) {
|
public void setType(String type) {
|
||||||
this.nodeId = nodeId;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType() {
|
public String getName() {
|
||||||
return type;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(String type) {
|
public void setName(String name) {
|
||||||
this.type = type;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getScript() {
|
||||||
return name;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setScript(String script) {
|
||||||
this.name = name;
|
this.script = script;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getScript() {
|
}
|
||||||
return script;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScript(String script) {
|
|
||||||
this.script = script;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user