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