feat: Simple设计器-监听器
This commit is contained in:
parent
34c8f4cae1
commit
955ad86db4
|
@ -96,20 +96,26 @@ public class BpmSimpleModelNodeVO {
|
|||
*/
|
||||
private AssignEmptyHandler assignEmptyHandler;
|
||||
|
||||
// TODO @lesan:建议改成 taskCreateListener;
|
||||
/**
|
||||
* 创建任务监听器
|
||||
*/
|
||||
private ListenerHandler createTaskListener;
|
||||
private ListenerHandler taskCreateListener;
|
||||
/**
|
||||
* 指派任务监听器
|
||||
*/
|
||||
private ListenerHandler taskAssignListener;
|
||||
/**
|
||||
* 完成任务监听器
|
||||
*/
|
||||
private ListenerHandler taskCompleteListener;
|
||||
|
||||
@Schema(description = "任务监听器")
|
||||
@Valid
|
||||
@Data
|
||||
public static class ListenerHandler {
|
||||
|
||||
// TODO @lesan:参数校验,需要加下
|
||||
|
||||
@Schema(description = "是否开启任务监听器", example = "false")
|
||||
@NotNull(message = "是否开启任务监听器不能为空")
|
||||
private Boolean enable;
|
||||
|
||||
@Schema(description = "请求路径", example = "http://xxxxx")
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.hutool.core.util.ArrayUtil;
|
|||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
|
@ -56,6 +57,18 @@ public class BpmnModelUtils {
|
|||
element.addExtensionElement(extensionElement);
|
||||
}
|
||||
|
||||
public static void addExtensionElementJson(FlowElement element, String name, Object value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
ExtensionElement extensionElement = new ExtensionElement();
|
||||
extensionElement.setNamespace(FLOWABLE_EXTENSIONS_NAMESPACE);
|
||||
extensionElement.setNamespacePrefix(FLOWABLE_EXTENSIONS_PREFIX);
|
||||
extensionElement.setElementText(JsonUtils.toJsonString(value));
|
||||
extensionElement.setName(name);
|
||||
element.addExtensionElement(extensionElement);
|
||||
}
|
||||
|
||||
public static void addExtensionElement(FlowElement element, String name, Integer value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
|
@ -93,6 +106,33 @@ public class BpmnModelUtils {
|
|||
return element != null ? element.getElementText() : null;
|
||||
}
|
||||
|
||||
public static <T> T parseExtensionElementJson(FlowElement flowElement, String elementName, Class<T> clazz) {
|
||||
if (flowElement == null) {
|
||||
return null;
|
||||
}
|
||||
ExtensionElement element = CollUtil.getFirst(flowElement.getExtensionElements().get(elementName));
|
||||
return element != null ? JsonUtils.parseObject(element.getElementText(), clazz) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给节点添加Simple设计器配置Json
|
||||
*
|
||||
* @param userTask 节点
|
||||
* @param node 节点对象
|
||||
*/
|
||||
public static void addSimpleConfigInfo(FlowElement userTask, Object node) {
|
||||
addExtensionElementJson(userTask, "config", node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析Simple设计器配置Json
|
||||
*
|
||||
* @param userTask 节点
|
||||
*/
|
||||
public static BpmSimpleModelNodeVO parseSimpleConfigInfo(FlowElement userTask) {
|
||||
return parseExtensionElementJson(userTask, "config", BpmSimpleModelNodeVO.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给节点添加候选人元素
|
||||
*
|
||||
|
|
|
@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
|
|||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups;
|
||||
|
@ -23,7 +22,6 @@ import java.util.*;
|
|||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*;
|
||||
import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION;
|
||||
import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.EXTENSION_SUFFIX;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
|
@ -442,23 +440,38 @@ public class SimpleModelUtils {
|
|||
userTask.setDueDate(node.getTimeoutHandler().getTimeDuration());
|
||||
}
|
||||
// 设置监听器
|
||||
addUserTaskListener(node, userTask);
|
||||
// 设置Simple设计器节点配置
|
||||
addSimpleConfigInfo(userTask, node);
|
||||
return userTask;
|
||||
}
|
||||
|
||||
private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) {
|
||||
List<FlowableListener> flowableListeners = new ArrayList<>(3);
|
||||
if (node.getCreateTaskListener().getEnable()) {
|
||||
if (node.getTaskCreateListener().getEnable()) {
|
||||
FlowableListener flowableListener = new FlowableListener();
|
||||
flowableListener.setEvent(TaskListener.EVENTNAME_CREATE);
|
||||
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
|
||||
flowableListener.setImplementation(DELEGATE_EXPRESSION);
|
||||
// TODO @lesan:可以加个 addExtensionElementJson() 方法;
|
||||
// TODO @lesan:是不是不用带 "create" + EXTENSION_SUFFIX 这种,直接给个 "config" 就完事了!
|
||||
addExtensionElement(userTask, "create" + EXTENSION_SUFFIX,
|
||||
// TODO @lesan:默认使用项目里的 JsonUtils 方法
|
||||
JSONUtil.toJsonStr(node.getCreateTaskListener()));
|
||||
flowableListeners.add(flowableListener);
|
||||
}
|
||||
if (node.getTaskAssignListener().getEnable()) {
|
||||
FlowableListener flowableListener = new FlowableListener();
|
||||
flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT);
|
||||
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
|
||||
flowableListener.setImplementation(DELEGATE_EXPRESSION);
|
||||
flowableListeners.add(flowableListener);
|
||||
}
|
||||
if (node.getTaskCompleteListener().getEnable()) {
|
||||
FlowableListener flowableListener = new FlowableListener();
|
||||
flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE);
|
||||
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
|
||||
flowableListener.setImplementation(DELEGATE_EXPRESSION);
|
||||
flowableListeners.add(flowableListener);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(flowableListeners)) {
|
||||
userTask.setTaskListeners(flowableListeners);
|
||||
}
|
||||
return userTask;
|
||||
}
|
||||
|
||||
private void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.task.listener;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmListenerMapType;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
|
@ -14,12 +14,18 @@ import org.flowable.bpmn.model.FlowElement;
|
|||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseExtensionElement;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseSimpleConfigInfo;
|
||||
|
||||
/**
|
||||
* BPM 用户任务通用监听器
|
||||
|
@ -32,52 +38,62 @@ public class BpmUserTaskListener implements TaskListener {
|
|||
|
||||
public static final String DELEGATE_EXPRESSION = "${bpmUserTaskListener}";
|
||||
|
||||
public static final String EXTENSION_SUFFIX = "TaskListenerMetaInfo";
|
||||
|
||||
@Resource
|
||||
private BpmModelService modelService;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
// 1. 获取所需基础信息
|
||||
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(delegateTask.getProcessInstanceId());
|
||||
BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(delegateTask.getProcessDefinitionId());
|
||||
FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, delegateTask.getTaskDefinitionKey());
|
||||
// TODO @lesan:可以写到 FlowableUtils 里,简化解析逻辑!
|
||||
BpmSimpleModelNodeVO.ListenerHandler listenerHandler = JSONUtil.toBean(
|
||||
parseExtensionElement(userTaskElement, delegateTask.getEventName() + EXTENSION_SUFFIX),
|
||||
BpmSimpleModelNodeVO.ListenerHandler.class);
|
||||
FlowElement userTask = BpmnModelUtils.getFlowElementById(bpmnModel, delegateTask.getTaskDefinitionKey());
|
||||
BpmSimpleModelNodeVO node = parseSimpleConfigInfo(userTask);
|
||||
BpmSimpleModelNodeVO.ListenerHandler listenerHandler = getListenerHandlerByEvent(delegateTask.getEventName(), node);
|
||||
|
||||
// 2. 获取请求头和请求体
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
listenerHandler.getHeader().forEach(item -> {
|
||||
// TODO @lesan:可以写个统一的方法,解析参数。然后非空,put 到 headers 或者 body 里!
|
||||
if (item.getType().equals(BpmListenerMapType.FIXED_VALUE.getType())) {
|
||||
headers.put(item.getKey(), item.getValue());
|
||||
} else if (item.getType().equals(BpmListenerMapType.FROM_FORM.getType())) {
|
||||
headers.put(item.getKey(), processVariables.getOrDefault(item.getValue(), "").toString());
|
||||
}
|
||||
});
|
||||
// TODO @lesan:header 里面,需要添加下 tenant-id!
|
||||
listenerHandler.getBody().forEach(item -> {
|
||||
if (item.getType().equals(BpmListenerMapType.FIXED_VALUE.getType())) {
|
||||
body.put(item.getKey(), item.getValue());
|
||||
} else if (item.getType().equals(BpmListenerMapType.FROM_FORM.getType())) {
|
||||
body.put(item.getKey(), processVariables.getOrDefault(item.getValue(), ""));
|
||||
}
|
||||
});
|
||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
|
||||
parseListenerMap(listenerHandler.getHeader(), processVariables, headers);
|
||||
headers.add("tenant-id", delegateTask.getTenantId());
|
||||
parseListenerMap(listenerHandler.getBody(), processVariables, body);
|
||||
|
||||
// 3. 异步发起请求
|
||||
// TODO @lesan:最好打印下日志!
|
||||
HttpRequest.post(listenerHandler.getPath())
|
||||
.addHeaders(headers).form(body).executeAsync();
|
||||
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
|
||||
ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST,
|
||||
requestEntity, String.class);
|
||||
log.info("[BpmUserTaskListener][的响应结果({})]", responseEntity);
|
||||
// 4. 是否需要后续操作?TODO 芋艿:待定!
|
||||
}
|
||||
|
||||
private void parseListenerMap(List<BpmSimpleModelNodeVO.ListenerHandler.ListenerMap> list,
|
||||
Map<String, Object> processVariables,
|
||||
MultiValueMap<String, String> to) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
list.forEach(item -> {
|
||||
if (item.getType().equals(BpmListenerMapType.FIXED_VALUE.getType())) {
|
||||
to.add(item.getKey(), item.getValue());
|
||||
} else if (item.getType().equals(BpmListenerMapType.FROM_FORM.getType())) {
|
||||
to.add(item.getKey(), processVariables.get(item.getValue()).toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private BpmSimpleModelNodeVO.ListenerHandler getListenerHandlerByEvent(String eventName, BpmSimpleModelNodeVO node) {
|
||||
return switch (eventName) {
|
||||
case TaskListener.EVENTNAME_CREATE -> node.getTaskCreateListener();
|
||||
case TaskListener.EVENTNAME_ASSIGNMENT -> node.getTaskAssignListener();
|
||||
case TaskListener.EVENTNAME_COMPLETE -> node.getTaskCompleteListener();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue