1
0

调整metadata的结构,使用更方便

This commit is contained in:
2025-01-03 15:27:40 +08:00
parent 57bc3fb2a8
commit 45ce5a2615
10 changed files with 134 additions and 37 deletions

View File

@@ -1,12 +1,12 @@
package com.lanyuanxiaoyao.flowable.jpa.entity; package com.lanyuanxiaoyao.flowable.jpa.entity;
import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Map;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EntityListeners; import javax.persistence.EntityListeners;
@@ -82,7 +82,7 @@ public class FlowableInstance {
return new com.lanyuanxiaoyao.flowable.core.model.FlowableInstance( return new com.lanyuanxiaoyao.flowable.core.model.FlowableInstance(
instanceId, instanceId,
currentNodeId, currentNodeId,
(Map<String, Object>) bytesToObject(this.metadata), (FlowableMetadata) bytesToObject(this.metadata),
status, status,
createdTime, createdTime,
updatedTime updatedTime

View File

@@ -5,7 +5,6 @@ import com.lanyuanxiaoyao.flowable.core.model.FlowableAction;
import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler;
import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance;
import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode;
import java.util.Map;
import javax.annotation.Resource; import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -19,7 +18,7 @@ public class SimpleAutoAction implements FlowableHandler {
private FlowableManager flowableManager; private FlowableManager flowableManager;
@Override @Override
public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map<String, Object> metadata) { public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) {
log.info("Initial with spring: {}", flowableManager.listNodes()); log.info("Initial with spring: {}", flowableManager.listNodes());
return FlowableAction.APPROVE; return FlowableAction.APPROVE;
} }

View File

@@ -33,6 +33,10 @@ public class MapHelper {
return Objects.isNull(map) || map.isEmpty(); return Objects.isNull(map) || map.isEmpty();
} }
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
@SafeVarargs @SafeVarargs
public static <K, V> Map<K, V> concat(Map<K, V>... maps) { public static <K, V> Map<K, V> concat(Map<K, V>... maps) {
Map<K, V> result = new HashMap<>(); Map<K, V> result = new HashMap<>();

View File

@@ -8,6 +8,7 @@ import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler;
import com.lanyuanxiaoyao.flowable.core.model.FlowableHistory; import com.lanyuanxiaoyao.flowable.core.model.FlowableHistory;
import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance;
import com.lanyuanxiaoyao.flowable.core.model.FlowableListener; 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.model.FlowableNode;
import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository; import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -67,11 +68,11 @@ public abstract class FlowableManager {
public String start(String nodeId, Map<String, Object> metadata) { public String start(String nodeId, Map<String, Object> metadata) {
FlowableNode node = repository.getNode(nodeId); 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); repository.saveInstance(instance);
if (FlowableNode.Type.AUTOMATIC.equals(node.getType())) { if (FlowableNode.Type.AUTOMATIC.equals(node.getType())) {
automaticAction(instance, node, MapHelper.empty()); automaticAction(instance, node);
} }
return instance.getInstanceId(); return instance.getInstanceId();
} }
@@ -106,16 +107,18 @@ public abstract class FlowableManager {
private void manualAction(String instanceId, FlowableAction action, String comment, Map<String, Object> metadata) { private void manualAction(String instanceId, FlowableAction action, String comment, Map<String, Object> metadata) {
FlowableInstance instance = repository.getInstance(instanceId); FlowableInstance instance = repository.getInstance(instanceId);
if (MapHelper.isNotEmpty(metadata)) {
instance.getMetadata().putAll(metadata);
}
FlowableNode node = repository.getNode(instance.getCurrentNodeId()); FlowableNode node = repository.getNode(instance.getCurrentNodeId());
metadata = MapHelper.isEmpty(metadata) ? instance.getMetadata() : MapHelper.concat(metadata, instance.getMetadata()); action(instance, node, action, comment);
action(instance, node, action, comment, metadata);
} }
private void automaticAction(FlowableInstance instance, FlowableNode node, Map<String, Object> metadata) { private void automaticAction(FlowableInstance instance, FlowableNode node) {
action(instance, node, null, "系统自动执行", metadata); action(instance, node, null, "系统自动执行");
} }
private void action(FlowableInstance instance, FlowableNode node, FlowableAction action, String comment, Map<String, Object> 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())) { if (FlowableInstance.Status.COMPLETED.equals(instance.getStatus()) || FlowableInstance.Status.ERROR.equals(instance.getStatus())) {
throw new IllegalArgumentException("ID为" + instance.getInstanceId() + "的流程已结束,无法操作"); throw new IllegalArgumentException("ID为" + instance.getInstanceId() + "的流程已结束,无法操作");
} }
@@ -125,42 +128,39 @@ public abstract class FlowableManager {
throw new IllegalArgumentException("节点执行器为空"); throw new IllegalArgumentException("节点执行器为空");
} }
FlowableHandler handler = createBean(handlerClass); FlowableHandler handler = createBean(handlerClass);
action = handler.handle(action, instance, node, metadata); action = handler.handle(instance, node, action);
if (Objects.isNull(action)) { if (Objects.isNull(action)) {
throw new IllegalArgumentException("节点执行结果不能为空"); throw new IllegalArgumentException("节点执行结果不能为空");
} }
// 如果是挂起操作,就直接返回,不做操作 // 如果是挂起操作,就直接返回,不做操作
if (FlowableAction.SUSPEND.equals(action)) { if (FlowableAction.SUSPEND.equals(action)) {
saveInstance(instance, instance.getStatus(), metadata, action, comment); saveInstance(instance, instance.getStatus(), action, comment);
return; return;
} }
if (FlowableAction.TERMINAL.equals(action)) { if (FlowableAction.TERMINAL.equals(action)) {
saveInstance(instance, FlowableInstance.Status.ERROR, metadata, action, comment); saveInstance(instance, FlowableInstance.Status.ERROR, action, comment);
return; return;
} }
if (Objects.isNull(node.getTargets()) if (Objects.isNull(node.getTargets())
|| !node.getTargets().containsKey(action) || !node.getTargets().containsKey(action)
|| StringHelper.isBlank(node.getTargets().get(action))) { || StringHelper.isBlank(node.getTargets().get(action))) {
saveInstance(instance, FlowableInstance.Status.COMPLETED, metadata, action, comment); saveInstance(instance, FlowableInstance.Status.COMPLETED, action, comment);
return; return;
} }
String nextNodeId = node.getTargets().get(action); String nextNodeId = node.getTargets().get(action);
FlowableNode nextNode = repository.getNode(nextNodeId); FlowableNode nextNode = repository.getNode(nextNodeId);
instance.setCurrentNodeId(nextNode.getNodeId()); 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())) { if (FlowableNode.Type.AUTOMATIC.equals(nextNode.getType())) {
automaticAction(instance, node, metadata); automaticAction(instance, node);
} }
} }
private void saveInstance(FlowableInstance instance, FlowableInstance.Status status, Map<String, Object> metadata, FlowableAction action, String comment) { private void saveInstance(FlowableInstance instance, FlowableInstance.Status status, FlowableAction action, String comment) {
instance.setStatus(status); instance.setStatus(status);
if (Objects.nonNull(metadata)) {
instance.addMetadata(metadata);
}
instance.setUpdatedTime(LocalDateTime.now()); instance.setUpdatedTime(LocalDateTime.now());
FlowableHistory history = new FlowableHistory(createId(), instance.getInstanceId(), action, comment); FlowableHistory history = new FlowableHistory(createId(), instance.getInstanceId(), action, comment);

View File

@@ -1,5 +1,7 @@
package com.lanyuanxiaoyao.flowable.core.model; package com.lanyuanxiaoyao.flowable.core.model;
import java.util.Map;
/** /**
* 权限校验 * 权限校验
* *
@@ -7,5 +9,5 @@ package com.lanyuanxiaoyao.flowable.core.model;
* @version 20241231 * @version 20241231
*/ */
public interface FlowableAccessor { public interface FlowableAccessor {
boolean access(Object accessor); boolean access(Map<String, Object> metadata);
} }

View File

@@ -1,7 +1,5 @@
package com.lanyuanxiaoyao.flowable.core.model; package com.lanyuanxiaoyao.flowable.core.model;
import java.util.Map;
/** /**
* 处理器 * 处理器
* *
@@ -9,11 +7,11 @@ import java.util.Map;
* @version 20250103 * @version 20250103
*/ */
public interface FlowableHandler { public interface FlowableHandler {
FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map<String, Object> metadata); FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action);
class DefaultFlowableHandler implements FlowableHandler { class DefaultFlowableHandler implements FlowableHandler {
@Override @Override
public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map<String, Object> metadata) { public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) {
return action; return action;
} }
} }

View File

@@ -1,6 +1,5 @@
package com.lanyuanxiaoyao.flowable.core.model; package com.lanyuanxiaoyao.flowable.core.model;
import com.lanyuanxiaoyao.flowable.core.helper.MapHelper;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Map; import java.util.Map;
import lombok.Data; import lombok.Data;
@@ -12,7 +11,7 @@ import lombok.Data;
@Data @Data
public class FlowableInstance { public class FlowableInstance {
private final String instanceId; private final String instanceId;
private final Map<String, Object> metadata; private final FlowableMetadata metadata;
private final LocalDateTime createdTime; private final LocalDateTime createdTime;
private String currentNodeId; private String currentNodeId;
@@ -20,14 +19,14 @@ public class FlowableInstance {
private LocalDateTime updatedTime; private LocalDateTime updatedTime;
public FlowableInstance(String instanceId, String currentNodeId) { 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<String, Object> metadata) { public FlowableInstance(String instanceId, String currentNodeId, FlowableMetadata metadata) {
this(instanceId, currentNodeId, metadata, Status.RUNNING, LocalDateTime.now(), LocalDateTime.now()); this(instanceId, currentNodeId, metadata, Status.RUNNING, LocalDateTime.now(), LocalDateTime.now());
} }
public FlowableInstance(String instanceId, String currentNodeId, Map<String, Object> 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.instanceId = instanceId;
this.metadata = metadata; this.metadata = metadata;
this.createdTime = createdTime; this.createdTime = createdTime;

View File

@@ -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<String, Object> metadata;
public FlowableMetadata() {
this(new HashMap<>());
}
public FlowableMetadata(Map<String, Object> 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> T get(String key, Class<T> 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<String, Object> m) {
metadata.putAll(m);
}
public Object getOrDefault(String key, Object defaultValue) {
return metadata.getOrDefault(key, defaultValue);
}
public <T> T getOrDefault(String key, Class<T> 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);
}
}

View File

@@ -3,8 +3,8 @@ package com.lanyuanxiaoyao.flowable.test.handler;
import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; import com.lanyuanxiaoyao.flowable.core.model.FlowableAction;
import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler;
import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance;
import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata;
import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode;
import java.util.Map;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**
@@ -18,9 +18,10 @@ public class TwoApproveHandler implements FlowableHandler {
private static final String KEY = "approve-times"; private static final String KEY = "approve-times";
@Override @Override
public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map<String, Object> metadata) { public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) {
log.info("{}", metadata); log.info("{}", instance.getMetadata());
int approveCount = (int) metadata.getOrDefault(KEY, 0); FlowableMetadata metadata = instance.getMetadata();
int approveCount = metadata.getIntOrDefault(KEY, 0);
if (approveCount + 1 > 1) { if (approveCount + 1 > 1) {
return FlowableAction.APPROVE; return FlowableAction.APPROVE;
} }

View File

@@ -4,7 +4,6 @@ import com.lanyuanxiaoyao.flowable.core.model.FlowableAction;
import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler; import com.lanyuanxiaoyao.flowable.core.model.FlowableHandler;
import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance;
import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; import com.lanyuanxiaoyao.flowable.core.model.FlowableNode;
import java.util.Map;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**
@@ -14,7 +13,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class SimpleAutoHandler implements FlowableHandler { public class SimpleAutoHandler implements FlowableHandler {
@Override @Override
public FlowableAction handle(FlowableAction action, FlowableInstance instance, FlowableNode node, Map<String, Object> metadata) { public FlowableAction handle(FlowableInstance instance, FlowableNode node, FlowableAction action) {
log.info("Simple handler initial"); log.info("Simple handler initial");
return FlowableAction.APPROVE; return FlowableAction.APPROVE;
} }