From 45ce5a26152ea47579d5a125fa6c168c5b37e5ab Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Fri, 3 Jan 2025 15:27:40 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4metadata=E7=9A=84=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E4=BD=BF=E7=94=A8=E6=9B=B4=E6=96=B9=E4=BE=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/jpa/entity/FlowableInstance.java | 4 +- .../flowable/jpa/SimpleAutoAction.java | 3 +- .../flowable/core/helper/MapHelper.java | 4 + .../core/manager/FlowableManager.java | 34 +++---- .../flowable/core/model/FlowableAccessor.java | 4 +- .../flowable/core/model/FlowableHandler.java | 6 +- .../flowable/core/model/FlowableInstance.java | 9 +- .../flowable/core/model/FlowableMetadata.java | 95 +++++++++++++++++++ .../test/handler/TwoApproveHandler.java | 9 +- .../flowable/test/SimpleAutoHandler.java | 3 +- 10 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableMetadata.java diff --git a/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/FlowableInstance.java b/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/FlowableInstance.java index 8b07e76..cfd6dc5 100644 --- a/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/FlowableInstance.java +++ b/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/FlowableInstance.java @@ -1,12 +1,12 @@ package com.lanyuanxiaoyao.flowable.jpa.entity; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.time.LocalDateTime; -import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EntityListeners; @@ -82,7 +82,7 @@ public class FlowableInstance { return new com.lanyuanxiaoyao.flowable.core.model.FlowableInstance( instanceId, currentNodeId, - (Map) bytesToObject(this.metadata), + (FlowableMetadata) bytesToObject(this.metadata), status, createdTime, updatedTime diff --git a/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SimpleAutoAction.java b/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SimpleAutoAction.java index 36a62d9..e07cc71 100644 --- a/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SimpleAutoAction.java +++ b/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SimpleAutoAction.java @@ -5,7 +5,6 @@ import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; -import java.util.Map; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -19,7 +18,7 @@ public class SimpleAutoAction implements FlowableHandler { private FlowableManager flowableManager; @Override - public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map metadata) { + public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) { log.info("Initial with spring: {}", flowableManager.listNodes()); return FlowableAction.APPROVE; } diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/helper/MapHelper.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/helper/MapHelper.java index 35f8561..d30e701 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/helper/MapHelper.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/helper/MapHelper.java @@ -33,6 +33,10 @@ public class MapHelper { return Objects.isNull(map) || map.isEmpty(); } + public static boolean isNotEmpty(Map map) { + return !isEmpty(map); + } + @SafeVarargs public static Map concat(Map... maps) { Map result = new HashMap<>(); diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java index 936ec04..63e5667 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java @@ -8,6 +8,7 @@ import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableHistory; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableListener; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository; import java.time.LocalDateTime; @@ -67,11 +68,11 @@ public abstract class FlowableManager { public String start(String nodeId, Map metadata) { FlowableNode node = repository.getNode(nodeId); - FlowableInstance instance = new FlowableInstance(createId(), node.getNodeId(), metadata); + FlowableInstance instance = new FlowableInstance(createId(), node.getNodeId(), new FlowableMetadata(metadata)); repository.saveInstance(instance); if (FlowableNode.Type.AUTOMATIC.equals(node.getType())) { - automaticAction(instance, node, MapHelper.empty()); + automaticAction(instance, node); } return instance.getInstanceId(); } @@ -106,16 +107,18 @@ public abstract class FlowableManager { private void manualAction(String instanceId, FlowableAction action, String comment, Map metadata) { FlowableInstance instance = repository.getInstance(instanceId); + if (MapHelper.isNotEmpty(metadata)) { + instance.getMetadata().putAll(metadata); + } FlowableNode node = repository.getNode(instance.getCurrentNodeId()); - metadata = MapHelper.isEmpty(metadata) ? instance.getMetadata() : MapHelper.concat(metadata, instance.getMetadata()); - action(instance, node, action, comment, metadata); + action(instance, node, action, comment); } - private void automaticAction(FlowableInstance instance, FlowableNode node, Map metadata) { - action(instance, node, null, "系统自动执行", metadata); + private void automaticAction(FlowableInstance instance, FlowableNode node) { + action(instance, node, null, "系统自动执行"); } - private void action(FlowableInstance instance, FlowableNode node, FlowableAction action, String comment, Map metadata) { + private void action(FlowableInstance instance, FlowableNode node, FlowableAction action, String comment) { if (FlowableInstance.Status.COMPLETED.equals(instance.getStatus()) || FlowableInstance.Status.ERROR.equals(instance.getStatus())) { throw new IllegalArgumentException("ID为" + instance.getInstanceId() + "的流程已结束,无法操作"); } @@ -125,42 +128,39 @@ public abstract class FlowableManager { throw new IllegalArgumentException("节点执行器为空"); } FlowableHandler handler = createBean(handlerClass); - action = handler.handle(action, instance, node, metadata); + action = handler.handle(instance, node, action); if (Objects.isNull(action)) { throw new IllegalArgumentException("节点执行结果不能为空"); } // 如果是挂起操作,就直接返回,不做操作 if (FlowableAction.SUSPEND.equals(action)) { - saveInstance(instance, instance.getStatus(), metadata, action, comment); + saveInstance(instance, instance.getStatus(), action, comment); return; } if (FlowableAction.TERMINAL.equals(action)) { - saveInstance(instance, FlowableInstance.Status.ERROR, metadata, action, comment); + saveInstance(instance, FlowableInstance.Status.ERROR, action, comment); return; } if (Objects.isNull(node.getTargets()) || !node.getTargets().containsKey(action) || StringHelper.isBlank(node.getTargets().get(action))) { - saveInstance(instance, FlowableInstance.Status.COMPLETED, metadata, action, comment); + saveInstance(instance, FlowableInstance.Status.COMPLETED, action, comment); return; } String nextNodeId = node.getTargets().get(action); FlowableNode nextNode = repository.getNode(nextNodeId); instance.setCurrentNodeId(nextNode.getNodeId()); - saveInstance(instance, FlowableInstance.Status.RUNNING, metadata, action, comment); + saveInstance(instance, FlowableInstance.Status.RUNNING, action, comment); if (FlowableNode.Type.AUTOMATIC.equals(nextNode.getType())) { - automaticAction(instance, node, metadata); + automaticAction(instance, node); } } - private void saveInstance(FlowableInstance instance, FlowableInstance.Status status, Map metadata, FlowableAction action, String comment) { + private void saveInstance(FlowableInstance instance, FlowableInstance.Status status, FlowableAction action, String comment) { instance.setStatus(status); - if (Objects.nonNull(metadata)) { - instance.addMetadata(metadata); - } instance.setUpdatedTime(LocalDateTime.now()); FlowableHistory history = new FlowableHistory(createId(), instance.getInstanceId(), action, comment); diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableAccessor.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableAccessor.java index 01dfa1f..9be8098 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableAccessor.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableAccessor.java @@ -1,5 +1,7 @@ package com.lanyuanxiaoyao.flowable.core.model; +import java.util.Map; + /** * 权限校验 * @@ -7,5 +9,5 @@ package com.lanyuanxiaoyao.flowable.core.model; * @version 20241231 */ public interface FlowableAccessor { - boolean access(Object accessor); + boolean access(Map metadata); } diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableHandler.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableHandler.java index ddb5a03..f77c212 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableHandler.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableHandler.java @@ -1,7 +1,5 @@ package com.lanyuanxiaoyao.flowable.core.model; -import java.util.Map; - /** * 处理器 * @@ -9,11 +7,11 @@ import java.util.Map; * @version 20250103 */ public interface FlowableHandler { - FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map metadata); + FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action); class DefaultFlowableHandler implements FlowableHandler { @Override - public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map metadata) { + public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) { return action; } } diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableInstance.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableInstance.java index 760aa6f..09a6bcb 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableInstance.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableInstance.java @@ -1,6 +1,5 @@ package com.lanyuanxiaoyao.flowable.core.model; -import com.lanyuanxiaoyao.flowable.core.helper.MapHelper; import java.time.LocalDateTime; import java.util.Map; import lombok.Data; @@ -12,7 +11,7 @@ import lombok.Data; @Data public class FlowableInstance { private final String instanceId; - private final Map metadata; + private final FlowableMetadata metadata; private final LocalDateTime createdTime; private String currentNodeId; @@ -20,14 +19,14 @@ public class FlowableInstance { private LocalDateTime updatedTime; public FlowableInstance(String instanceId, String currentNodeId) { - this(instanceId, currentNodeId, MapHelper.empty(), Status.RUNNING, LocalDateTime.now(), LocalDateTime.now()); + this(instanceId, currentNodeId, new FlowableMetadata(), Status.RUNNING, LocalDateTime.now(), LocalDateTime.now()); } - public FlowableInstance(String instanceId, String currentNodeId, Map metadata) { + public FlowableInstance(String instanceId, String currentNodeId, FlowableMetadata metadata) { this(instanceId, currentNodeId, metadata, Status.RUNNING, LocalDateTime.now(), LocalDateTime.now()); } - public FlowableInstance(String instanceId, String currentNodeId, Map metadata, Status status, LocalDateTime createdTime, LocalDateTime updatedTime) { + public FlowableInstance(String instanceId, String currentNodeId, FlowableMetadata metadata, Status status, LocalDateTime createdTime, LocalDateTime updatedTime) { this.instanceId = instanceId; this.metadata = metadata; this.createdTime = createdTime; diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableMetadata.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableMetadata.java new file mode 100644 index 0000000..77021a7 --- /dev/null +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableMetadata.java @@ -0,0 +1,95 @@ +package com.lanyuanxiaoyao.flowable.core.model; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import lombok.ToString; + +/** + * 节点流转上下文 + * + * @author lanyuanxiaoyao + * @version 20250103 + */ +@ToString +@Getter +public class FlowableMetadata implements Serializable { + private final Map metadata; + + public FlowableMetadata() { + this(new HashMap<>()); + } + + public FlowableMetadata(Map metadata) { + this.metadata = metadata; + } + + public Object put(String key, Object value) { + return metadata.put(key, value); + } + + public Object get(String key) { + return metadata.get(key); + } + + public T get(String key, Class clazz) { + return clazz.cast(metadata.get(key)); + } + + public Integer getInt(String key) { + return get(key, Integer.class); + } + + public Long getLong(String key) { + return get(key, Long.class); + } + + public Boolean getBoolean(String key) { + return get(key, Boolean.class); + } + + public boolean isEmpty() { + return metadata.isEmpty(); + } + + public int size() { + return metadata.size(); + } + + public boolean containsKey(String key) { + return metadata.containsKey(key); + } + + public boolean containsValue(String value) { + return metadata.containsValue(value); + } + + public Object remove(String key) { + return metadata.remove(key); + } + + public void putAll(Map m) { + metadata.putAll(m); + } + + public Object getOrDefault(String key, Object defaultValue) { + return metadata.getOrDefault(key, defaultValue); + } + + public T getOrDefault(String key, Class clazz, T defaultValue) { + return clazz.cast(metadata.getOrDefault(key, defaultValue)); + } + + public Integer getIntOrDefault(String key, Integer defaultValue) { + return getOrDefault(key, Integer.class, defaultValue); + } + + public Long getLongOrDefault(String key, Long defaultValue) { + return getOrDefault(key, Long.class, defaultValue); + } + + public Boolean getBooleanOrDefault(String key, Boolean defaultValue) { + return getOrDefault(key, Boolean.class, defaultValue); + } +} diff --git a/flowable-example/src/main/java/com/lanyuanxiaoyao/flowable/test/handler/TwoApproveHandler.java b/flowable-example/src/main/java/com/lanyuanxiaoyao/flowable/test/handler/TwoApproveHandler.java index 5ab8d90..26cb732 100644 --- a/flowable-example/src/main/java/com/lanyuanxiaoyao/flowable/test/handler/TwoApproveHandler.java +++ b/flowable-example/src/main/java/com/lanyuanxiaoyao/flowable/test/handler/TwoApproveHandler.java @@ -3,8 +3,8 @@ package com.lanyuanxiaoyao.flowable.test.handler; import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; -import java.util.Map; import lombok.extern.slf4j.Slf4j; /** @@ -18,9 +18,10 @@ public class TwoApproveHandler implements FlowableHandler { private static final String KEY = "approve-times"; @Override - public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map metadata) { - log.info("{}", metadata); - int approveCount = (int) metadata.getOrDefault(KEY, 0); + public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) { + log.info("{}", instance.getMetadata()); + FlowableMetadata metadata = instance.getMetadata(); + int approveCount = metadata.getIntOrDefault(KEY, 0); if (approveCount + 1 > 1) { return FlowableAction.APPROVE; } diff --git a/flowable-example/src/test/java/com/lanyuanxiaoyao/flowable/test/SimpleAutoHandler.java b/flowable-example/src/test/java/com/lanyuanxiaoyao/flowable/test/SimpleAutoHandler.java index d282bbf..a71a8cb 100644 --- a/flowable-example/src/test/java/com/lanyuanxiaoyao/flowable/test/SimpleAutoHandler.java +++ b/flowable-example/src/test/java/com/lanyuanxiaoyao/flowable/test/SimpleAutoHandler.java @@ -4,7 +4,6 @@ import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; -import java.util.Map; import lombok.extern.slf4j.Slf4j; /** @@ -14,7 +13,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class SimpleAutoHandler implements FlowableHandler { @Override - public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map metadata) { + public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) { log.info("Simple handler initial"); return FlowableAction.APPROVE; }