From 931e6da455c3353e7d35e6e0863022c311427fe5 Mon Sep 17 00:00:00 2001 From: zendwang Date: Tue, 2 Aug 2022 17:19:52 +0800 Subject: [PATCH] =?UTF-8?q?refactor=20#I5EU86=20=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E7=B1=BB=E5=BA=93fastjson=E8=BD=AC=E4=B8=BAjackson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- liteflow-core/pom.xml | 4 + .../liteflow/builder/prop/FlowPropBean.java | 11 ++ .../exception/JsonProcessException.java | 22 ++++ .../liteflow/parser/JsonFlowParser.java | 3 +- .../parser/ZookeeperJsonFlowParser.java | 3 +- .../parser/base/BaseJsonFlowParser.java | 13 +- .../base/BaseZookeeperJsonFlowParser.java | 3 +- .../liteflow/parser/el/JsonFlowELParser.java | 3 +- .../parser/el/ZookeeperJsonFlowELParser.java | 3 +- .../liteflow/parser/helper/ParserHelper.java | 112 ++++++++++++++++++ .../com/yomahub/liteflow/util/JsonUtil.java | 109 +++++++++++++++++ .../liteflow-testcase-el-nospring/pom.xml | 4 + .../liteflow/test/util/ParserHelperTest.java | 30 +++++ pom.xml | 6 + 14 files changed, 315 insertions(+), 11 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/FlowPropBean.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/exception/JsonProcessException.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/util/JsonUtil.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/util/ParserHelperTest.java diff --git a/liteflow-core/pom.xml b/liteflow-core/pom.xml index 27e3cd25f..36da275f0 100644 --- a/liteflow-core/pom.xml +++ b/liteflow-core/pom.xml @@ -32,6 +32,10 @@ com.alibaba fastjson + + com.fasterxml.jackson.core + jackson-databind + org.yaml snakeyaml diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/FlowPropBean.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/FlowPropBean.java new file mode 100644 index 000000000..9a52a6c6a --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/FlowPropBean.java @@ -0,0 +1,11 @@ +package com.yomahub.liteflow.builder.prop; + +import java.util.List; + +/** + * 构建 node 的中间属性 + */ +public class FlowPropBean { + List nodes; + List chain; +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/JsonProcessException.java b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/JsonProcessException.java new file mode 100644 index 000000000..98a07be82 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/JsonProcessException.java @@ -0,0 +1,22 @@ +package com.yomahub.liteflow.exception; + +public class JsonProcessException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** 异常信息 */ + private String message; + + public JsonProcessException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java index 09ff2e267..eb108061d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.parser; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.builder.LiteFlowChainBuilder; import com.yomahub.liteflow.builder.prop.ChainPropBean; import com.yomahub.liteflow.enums.ConditionTypeEnum; @@ -28,7 +29,7 @@ public abstract class JsonFlowParser extends BaseJsonFlowParser { * 解析一个chain的过程 */ @Override - public void parseOneChain(JSONObject chainObject) { + public void parseOneChain(JsonNode chainObject) { ParserHelper.parseOneChain(chainObject); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperJsonFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperJsonFlowParser.java index 6a7d4654b..dd70693be 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperJsonFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperJsonFlowParser.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.parser; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.parser.base.BaseZookeeperJsonFlowParser; import com.yomahub.liteflow.parser.helper.ParserHelper; @@ -16,7 +17,7 @@ public class ZookeeperJsonFlowParser extends BaseZookeeperJsonFlowParser { } @Override - public void parseOneChain(JSONObject chainObject) { + public void parseOneChain(JsonNode chainObject) { ParserHelper.parseOneChain(chainObject); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseJsonFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseJsonFlowParser.java index a6ea0cb2c..0446c2edf 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseJsonFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseJsonFlowParser.java @@ -4,7 +4,9 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.parser.helper.ParserHelper; +import com.yomahub.liteflow.util.JsonUtil; import java.util.List; import java.util.Set; @@ -30,13 +32,12 @@ public abstract class BaseJsonFlowParser implements FlowParser { return; } - List jsonObjectList = ListUtil.toList(); + List jsonObjectList = ListUtil.toList(); for (String content : contentList) { - //把字符串原生转换为json对象,如果不加第二个参数OrderedField,会无序 - JSONObject flowJsonObject = JSONObject.parseObject(content, Feature.OrderedField); - jsonObjectList.add(flowJsonObject); + JsonNode flowJsonNode = JsonUtil.parseObject(content); + jsonObjectList.add(flowJsonNode); } - ParserHelper.parseJsonObject(jsonObjectList, CHAIN_NAME_SET, this::parseOneChain); + ParserHelper.parseJsonNode(jsonObjectList, CHAIN_NAME_SET, this::parseOneChain); } /** @@ -44,6 +45,6 @@ public abstract class BaseJsonFlowParser implements FlowParser { * * @param chainObject chain 节点 */ - public abstract void parseOneChain(JSONObject chainObject); + public abstract void parseOneChain(JsonNode chainObject); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperJsonFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperJsonFlowParser.java index f64c6f1df..dc10f85c2 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperJsonFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperJsonFlowParser.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.parser.base; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.parser.ZookeeperJsonFlowParser; import com.yomahub.liteflow.parser.helper.ZkParserHelper; import org.apache.curator.framework.CuratorFramework; @@ -54,5 +55,5 @@ public abstract class BaseZookeeperJsonFlowParser extends BaseJsonFlowParser { * @param chainObject chain 节点 */ @Override - public abstract void parseOneChain(JSONObject chainObject); + public abstract void parseOneChain(JsonNode chainObject); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/JsonFlowELParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/JsonFlowELParser.java index 1c046ac32..908dec4cc 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/JsonFlowELParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/JsonFlowELParser.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.parser.el; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.parser.base.BaseJsonFlowParser; import com.yomahub.liteflow.parser.helper.ParserHelper; @@ -21,7 +22,7 @@ public abstract class JsonFlowELParser extends BaseJsonFlowParser { * @param chainObject chain 节点 */ @Override - public void parseOneChain(JSONObject chainObject) { + public void parseOneChain(JsonNode chainObject) { ParserHelper.parseOneChainEl(chainObject); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/ZookeeperJsonFlowELParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/ZookeeperJsonFlowELParser.java index 55de68777..506740886 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/ZookeeperJsonFlowELParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/el/ZookeeperJsonFlowELParser.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.parser.el; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.parser.base.BaseZookeeperJsonFlowParser; import com.yomahub.liteflow.parser.helper.ParserHelper; @@ -16,7 +17,7 @@ public class ZookeeperJsonFlowELParser extends BaseZookeeperJsonFlowParser { } @Override - public void parseOneChain(JSONObject chainObject) { + public void parseOneChain(JsonNode chainObject) { ParserHelper.parseOneChainEl(chainObject); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java index f9cbde391..665339e2a 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java @@ -7,6 +7,7 @@ import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; import com.yomahub.liteflow.annotation.LiteflowSwitchCmpDefine; import com.yomahub.liteflow.builder.LiteFlowChainBuilder; @@ -286,6 +287,65 @@ public class ParserHelper { } } + public static void parseJsonNode(List flowJsonObjectList, Set chainNameSet, Consumer parseOneChainConsumer) { + //先在元数据里放上chain + //先放有一个好处,可以在parse的时候先映射到FlowBus的chainMap,然后再去解析 + //这样就不用去像之前的版本那样回归调用 + //同时也解决了不能循环依赖的问题 + flowJsonObjectList.forEach(jsonObject -> { + // 解析chain节点 + Iterator iterator = jsonObject.get(FLOW).get(CHAIN).elements(); + //先在元数据里放上chain + while (iterator.hasNext()) { + JsonNode innerJsonObject = iterator.next(); + //校验加载的 chainName 是否有重复的 + // TODO 这里是否有个问题,当混合格式加载的时候,2个同名的Chain在不同的文件里,就不行了 + String chainName = innerJsonObject.get(NAME).textValue(); + if (!chainNameSet.add(chainName)) { + throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName)); + } + + FlowBus.addChain(innerJsonObject.get(NAME).textValue()); + } + }); + // 清空 + chainNameSet.clear(); + + for (JsonNode flowJsonNode : flowJsonObjectList) { + // 当存在节点定义时,解析node节点 + if (flowJsonNode.get(FLOW).has(NODES)) { + Iterator nodeIterator = flowJsonNode.get(FLOW).get(NODES).get(NODE).elements(); + String id, name, clazz, script, type, file; + while ((nodeIterator.hasNext())) { + JsonNode nodeObject = nodeIterator.next(); + id = nodeObject.get(ID).textValue(); + name = nodeObject.hasNonNull(NAME) ? nodeObject.get(NAME).textValue() : ""; + clazz = nodeObject.get(_CLASS).textValue(); + type = nodeObject.hasNonNull(TYPE) ? nodeObject.get(TYPE).textValue() : ""; + script = nodeObject.hasNonNull(VALUE) ? nodeObject.get(VALUE).textValue() : ""; + file = nodeObject.hasNonNull(FILE) ? nodeObject.get(FILE).textValue() : ""; + + // 构建 node + NodePropBean nodePropBean = new NodePropBean() + .setId(id) + .setName(name) + .setClazz(clazz) + .setScript(script) + .setType(type) + .setFile(file); + + ParserHelper.buildNode(nodePropBean); + } + } + + //解析每一个chain + Iterator chainIterator = flowJsonNode.get(FLOW).get(CHAIN).elements(); + while (chainIterator.hasNext()) { + JsonNode jsonNode = chainIterator.next(); + parseOneChainConsumer.accept(jsonNode); + } + } + } /** * 解析一个chain的过程 * @@ -325,6 +385,44 @@ public class ParserHelper { } } + /** + * 解析一个chain的过程 + * + * @param chainNode chain 节点 + */ + public static void parseOneChain(JsonNode chainNode) { + String condValueStr; + ConditionTypeEnum conditionType; + String group; + String errorResume; + String any; + String threadExecutorClass; + + //构建chainBuilder + String chainName = chainNode.get(NAME).textValue(); + LiteFlowChainBuilder chainBuilder = LiteFlowChainBuilder.createChain().setChainName(chainName); + Iterator iterator = chainNode.get(CONDITION).iterator(); + while (iterator.hasNext()) { + JsonNode condNode = iterator.next(); + conditionType = ConditionTypeEnum.getEnumByCode(condNode.get(TYPE).textValue()); + condValueStr = condNode.get(VALUE).textValue(); + errorResume = condNode.get(ERROR_RESUME).textValue(); + group = condNode.get(GROUP).textValue(); + any = condNode.get(ANY).textValue(); + threadExecutorClass = condNode.get(THREAD_EXECUTOR_CLASS).textValue(); + + ChainPropBean chainPropBean = new ChainPropBean() + .setCondValueStr(condValueStr) + .setGroup(group) + .setErrorResume(errorResume) + .setAny(any) + .setThreadExecutorClass(threadExecutorClass) + .setConditionType(conditionType); + + // 构建 chain + ParserHelper.buildChain(chainPropBean, chainBuilder); + } + } /** * 解析一个chain的过程 *

@@ -364,6 +462,20 @@ public class ParserHelper { } } + /** + * 解析一个chain的过程 + * + * @param chainNode chain 节点 + */ + public static void parseOneChainEl(JsonNode chainNode) { + //构建chainBuilder + String chainName = chainNode.get(NAME).textValue(); + String el = chainNode.get(VALUE).textValue(); + LiteFlowChainELBuilder chainELBuilder = LiteFlowChainELBuilder.createChain().setChainName(chainName); + chainELBuilder.setEL(el).build(); + } + + /** * 解析一个chain的过程 * diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/JsonUtil.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/JsonUtil.java new file mode 100644 index 000000000..871609cc4 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/JsonUtil.java @@ -0,0 +1,109 @@ +package com.yomahub.liteflow.util; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yomahub.liteflow.exception.JsonProcessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * JSON 工具类 + * + * @author zendwang + */ +public class JsonUtil { + + private static final Logger LOG = LoggerFactory.getLogger(JsonUtil.class); + + private static ObjectMapper objectMapper = new ObjectMapper(); + + private JsonUtil() { + } + + public static String toJsonString(Object object) { + if (ObjectUtil.isNull(object)) { + return null; + } + try { + return objectMapper.writeValueAsString(object); + } catch (JsonProcessingException e) { + String errMsg = StrUtil.format("Error while writing value as string[{}]",object.getClass().getName()); + LOG.error(errMsg); + throw new JsonProcessException(errMsg); + } + } + + public static JsonNode parseObject(String text) { + if (StrUtil.isEmpty(text)) { + return null; + } + try { + return objectMapper.readTree(text); + } catch (IOException e) { + String errMsg = StrUtil.format("Error while parsing text [{}]",text); + LOG.error(errMsg); + throw new JsonProcessException(errMsg); + } + } + + public static T parseObject(String text, Class clazz) { + if (StrUtil.isEmpty(text)) { + return null; + } + try { + return objectMapper.readValue(text, clazz); + } catch (IOException e) { + String errMsg = StrUtil.format("Error while parsing text[{}] to object[{}]",text, clazz.getClass().getName()); + LOG.error(errMsg); + throw new JsonProcessException(errMsg); + } + } + + public static T parseObject(String text, TypeReference typeReference) { + if (StrUtil.isBlank(text)) { + return null; + } + try { + return objectMapper.readValue(text, typeReference); + } catch (IOException e) { + String errMsg = StrUtil.format("Error while parsing text[{}] to object[{}]",text, typeReference.getClass().getName()); + LOG.error(errMsg); + throw new JsonProcessException(errMsg); + } + } + + public static Map parseMap(String text) { + if (StrUtil.isBlank(text)) { + return null; + } + try { + return objectMapper.readValue(text, new TypeReference>() { + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArray(String text, Class clazz) { + if (StrUtil.isEmpty(text)) { + return new ArrayList<>(); + } + try { + return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/pom.xml index 09ea7ddb3..b270207a2 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/pom.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/pom.xml @@ -47,6 +47,10 @@ org.apache.curator curator-recipes + + com.fasterxml.jackson.core + jackson-databind + diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/util/ParserHelperTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/util/ParserHelperTest.java new file mode 100644 index 000000000..c53293b02 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/util/ParserHelperTest.java @@ -0,0 +1,30 @@ +package com.yomahub.liteflow.test.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.yomahub.liteflow.parser.helper.ParserHelper; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.Test; + +import java.util.Iterator; + +import static com.yomahub.liteflow.common.ChainConstant.NAME; +import static com.yomahub.liteflow.common.ChainConstant.VALUE; + +public class ParserHelperTest { + + private final static String FLOW_JSON = "{\"flow\":{\"nodes\":{\"node\":[{\"id\":\"a\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.ACmp\"},{\"id\":\"b\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.BCmp\"},{\"id\":\"c\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.CCmp\"},{\"id\":\"d\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.DCmp\"},{\"id\":\"e\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.ECmp\"},{\"id\":\"f\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.FCmp\"},{\"id\":\"g\",\"class\":\"com.yomahub.liteflow.test.parser.cmp.GCmp\"}]},\"chain\":[{\"name\":\"chain2\",\"value\":\"THEN(c,g,f);\"},{\"name\":\"chain1\",\"value\":\"THEN(a,c,WHEN(b,d,SWITCH(e).to(f,g)), chain2);\"}]}}"; + + + @Test + public void testParseOneChainEl4JsonNode() { + JsonNode rootNode = JsonUtil.parseObject(FLOW_JSON); + Iterator iterator = rootNode.path("flow").path("chain").iterator(); + while (iterator.hasNext()) { + JsonNode chainNode = iterator.next(); + String chainName = chainNode.get(NAME).textValue(); + String el = chainNode.get(VALUE).textValue(); + System.out.println(chainName + "-" + el); + } + + } +} diff --git a/pom.xml b/pom.xml index 45bb8aaba..bb2a2ee95 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,7 @@ 5.0.9.RELEASE 1.7.32 1.2.79 + 2.9.6 1.29 2.1.3 5.1.0 @@ -110,6 +111,11 @@ fastjson ${fastjson.version} + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + org.yaml snakeyaml