Commit d0fbb7677cb0d49e06efc10cfadb374ccbd92fc1
1 parent
fda6aff8
【代码评审】BPM:触发器 HTTP 异步
Showing
15 changed files
with
44 additions
and
31 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.api.task; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| 4 | - | |
| 5 | 4 | import jakarta.validation.Valid; |
| 6 | 5 | |
| 7 | 6 | /** |
| ... | ... | @@ -20,12 +19,13 @@ public interface BpmProcessInstanceApi { |
| 20 | 19 | */ |
| 21 | 20 | String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO); |
| 22 | 21 | |
| 23 | - | |
| 22 | + // TODO @jason:新增 BpmProcessTaskApi 接口,这个要不改成 triggerTask,保持通用性(和 flowable 保持一致) | |
| 24 | 23 | /** |
| 25 | 24 | * 异步 HTTP 请求触发器回调, 为了唤醒流程继续执行 |
| 26 | 25 | * |
| 27 | 26 | * @param processInstanceId 流程实例编号 |
| 28 | - * @param callbackId 回调编号, 对应 ReceiveTask Id | |
| 27 | + * @param callbackId 回调编号, 对应 ReceiveTask Id TODO @jason:改成 taskDefineKey | |
| 29 | 28 | */ |
| 30 | 29 | void asyncHttpTriggerCallback(String processInstanceId, String callbackId); |
| 30 | + | |
| 31 | 31 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java
| ... | ... | @@ -19,7 +19,7 @@ public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> { |
| 19 | 19 | HTTP_REQUEST(1, "发起 HTTP 请求"), |
| 20 | 20 | FORM_UPDATE(2, "更新流程表单数据"), |
| 21 | 21 | FORM_DELETE(3, "删除流程表单数据"), |
| 22 | - ASYNC_HTTP_REQUEST(4, "发起异步 HTTP 请求"); | |
| 22 | + ASYNC_HTTP_REQUEST(4, "发起异步 HTTP 请求"); // TODO @jason:HTTP_REQUEST_ASYNC | |
| 23 | 23 | |
| 24 | 24 | /** |
| 25 | 25 | * 触发器执行动作类型 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| ... | ... | @@ -117,7 +117,8 @@ public class BpmSimpleModelNodeVO { |
| 117 | 117 | @Schema(description = "路由分支组", example = "[]") |
| 118 | 118 | private List<RouterSetting> routerGroups; |
| 119 | 119 | |
| 120 | - @Schema(description = "路由分支默认分支 ID", example = "Flow_xxx", hidden = true) // 由后端生成,所以 hidden = true | |
| 120 | + @Schema(description = "路由分支默认分支 ID", example = "Flow_xxx", hidden = true) // 由后端生成(不从前端传递),所以 hidden = true | |
| 121 | + @JsonIgnore | |
| 121 | 122 | private String routerDefaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTER_BRANCH_NODE |
| 122 | 123 | |
| 123 | 124 | /** |
| ... | ... | @@ -125,12 +126,9 @@ public class BpmSimpleModelNodeVO { |
| 125 | 126 | */ |
| 126 | 127 | private TriggerSetting triggerSetting; |
| 127 | 128 | |
| 128 | - /** | |
| 129 | - * 附加节点 Id, 该节点不从前端传入。 由程序生成. 由于当个节点无法完成功能。 需要附加节点来完成。 | |
| 130 | - */ | |
| 129 | + @Schema(description = "附加节点 Id", example = "UserTask_xxx", hidden = true) // 由后端生成(不从前端传递),所以 hidden = true | |
| 131 | 130 | @JsonIgnore |
| 132 | - private String attachNodeId; // 目前用于异步触发器节点。需要 UserTask 和 ReceiveTask(附加节点) 来完成 | |
| 133 | - | |
| 131 | + private String attachNodeId; // 目前用于触发器节点(异步)。需要 UserTask 和 ReceiveTask(附加节点) 来完成 | |
| 134 | 132 | |
| 135 | 133 | /** |
| 136 | 134 | * 子流程设置 |
| ... | ... | @@ -382,7 +380,6 @@ public class BpmSimpleModelNodeVO { |
| 382 | 380 | @Valid |
| 383 | 381 | private List<HttpRequestParam> body; |
| 384 | 382 | |
| 385 | - // TODO @json:可能未来看情况,搞个 HttpResponseParam;得看看有没别的业务需要,抽象统一 | |
| 386 | 383 | /** |
| 387 | 384 | * 请求返回处理设置,用于修改流程表单值 |
| 388 | 385 | * <p> |
| ... | ... | @@ -392,10 +389,13 @@ public class BpmSimpleModelNodeVO { |
| 392 | 389 | @Schema(description = "请求返回处理设置", example = "[]") |
| 393 | 390 | private List<KeyValue<String, String>> response; |
| 394 | 391 | |
| 392 | + // TODO @jason:改成 callbackTaskDefineKey | |
| 395 | 393 | /** |
| 396 | - * 异步 Http 请求,需要指定回调 Id,用于回调执行. 由后端指定 | |
| 394 | + * 异步 Http 请求,需要指定回调 ID,用于回调执行 | |
| 397 | 395 | */ |
| 396 | + @Schema(description = "回调 ID", example = "xxx", hidden = true) | |
| 398 | 397 | private String callbackId; |
| 398 | + | |
| 399 | 399 | } |
| 400 | 400 | |
| 401 | 401 | @Schema(description = "流程表单触发器设置", example = "{}") | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
| ... | ... | @@ -180,6 +180,7 @@ public class BpmProcessInstanceController { |
| 180 | 180 | return success(processInstanceService.getProcessInstanceBpmnModelView(id)); |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | + // TODO @jason:要不去掉这个接口,单体通过 asyncHttpTriggerCallback? | |
| 183 | 184 | @PostMapping("/http-trigger/callback") |
| 184 | 185 | @Operation(summary = "异步 HTTP 请求触发器回调") |
| 185 | 186 | @PermitAll // 允许外部调用,不需要登录。 TODO @芋艿 需要加一下验证签名吗? | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmHttpTriggerCallbackReqVO.java
| ... | ... | @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import jakarta.validation.constraints.NotEmpty; |
| 5 | 5 | import lombok.Data; |
| 6 | 6 | |
| 7 | +// TODO @jason:要不去掉这个接口,单体通过 asyncHttpTriggerCallback? | |
| 7 | 8 | @Schema(description = "管理后台 - Bpm 异步 Http 触发器请求回调 Request VO") |
| 8 | 9 | @Data |
| 9 | 10 | public class BpmHttpTriggerCallbackReqVO { |
| ... | ... | @@ -15,4 +16,5 @@ public class BpmHttpTriggerCallbackReqVO { |
| 15 | 16 | @Schema(description = "回调编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "dca1cdcc-b8fe-11ef-99b5-01ff4722db8b") |
| 16 | 17 | @NotEmpty(message = "回调编号不能为空") |
| 17 | 18 | private String callbackId; |
| 19 | + | |
| 18 | 20 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| ... | ... | @@ -171,11 +171,12 @@ public class SimpleModelUtils { |
| 171 | 171 | // 情况二:没有“子节点”,则直接跟 targetNodeId 建立连线。例如说,结束节点、条件分支(分支节点的孩子节点或聚合节点)的最后一个节点 |
| 172 | 172 | String finalTargetNodeId = isChildNodeValid ? childNode.getId() : targetNodeId; |
| 173 | 173 | |
| 174 | + // 如果没有附加节点:则直接建立连线 | |
| 174 | 175 | if (StrUtil.isEmpty(node.getAttachNodeId())) { |
| 175 | 176 | SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), finalTargetNodeId); |
| 176 | 177 | process.addFlowElement(sequenceFlow); |
| 177 | 178 | } else { |
| 178 | - // 如果有附加节点. 需要先建立和附加节点的连线。再建立附加节点和目标节点的连线 | |
| 179 | + // 如果有附加节点:需要先建立和附加节点的连线,再建立附加节点和目标节点的连线。例如说,触发器节点(异步) | |
| 179 | 180 | List<SequenceFlow> sequenceFlows = buildAttachNodeSequenceFlow(node.getId(), node.getAttachNodeId(), finalTargetNodeId); |
| 180 | 181 | sequenceFlows.forEach(process::addFlowElement); |
| 181 | 182 | } |
| ... | ... | @@ -189,9 +190,9 @@ public class SimpleModelUtils { |
| 189 | 190 | /** |
| 190 | 191 | * 构建有附加节点的连线 |
| 191 | 192 | * |
| 192 | - * @param nodeId 当前节点 Id | |
| 193 | - * @param attachNodeId 附属节点 Id | |
| 194 | - * @param targetNodeId 目标节点 Id | |
| 193 | + * @param nodeId 当前节点 ID | |
| 194 | + * @param attachNodeId 附属节点 ID | |
| 195 | + * @param targetNodeId 目标节点 ID | |
| 195 | 196 | */ |
| 196 | 197 | private static List<SequenceFlow> buildAttachNodeSequenceFlow(String nodeId, String attachNodeId, String targetNodeId) { |
| 197 | 198 | SequenceFlow sequenceFlow = buildBpmnSequenceFlow(nodeId, attachNodeId, null, null, null); |
| ... | ... | @@ -748,8 +749,10 @@ public class SimpleModelUtils { |
| 748 | 749 | |
| 749 | 750 | public static class TriggerNodeConvert implements NodeConvert { |
| 750 | 751 | |
| 752 | + // TODO @芋艿:【异步】在看看 | |
| 751 | 753 | @Override |
| 752 | 754 | public List<? extends FlowElement> convertList(BpmSimpleModelNodeVO node) { |
| 755 | + Assert.notNull(node.getTriggerSetting(), "触发器节点设置不能为空"); | |
| 753 | 756 | List<FlowElement> flowElements = new ArrayList<>(2); |
| 754 | 757 | // 触发器使用 ServiceTask 来实现 |
| 755 | 758 | ServiceTask serviceTask = new ServiceTask(); |
| ... | ... | @@ -757,23 +760,23 @@ public class SimpleModelUtils { |
| 757 | 760 | serviceTask.setName(node.getName()); |
| 758 | 761 | serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); |
| 759 | 762 | serviceTask.setImplementation("${" + BpmTriggerTaskDelegate.BEAN_NAME + "}"); |
| 760 | - Assert.notNull(node.getTriggerSetting(), "触发器节点设置不能为空"); | |
| 761 | - | |
| 762 | 763 | addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType()); |
| 763 | 764 | flowElements.add(serviceTask); |
| 765 | + | |
| 764 | 766 | // 异步 HTTP 请求。需要附加一个 ReceiveTask、发起请求后、等待回调执行 |
| 767 | + // TODO @jason:这里能挪到最后处理么?这样,代码的整体性更好; | |
| 765 | 768 | if (ASYNC_HTTP_REQUEST.getType().equals(node.getTriggerSetting().getType())) { |
| 769 | + Assert.notNull(node.getTriggerSetting().getHttpRequestSetting(), "触发器 HTTP 请求设置不能为空"); | |
| 766 | 770 | String attachNodeId = "Activity_" + IdUtil.fastUUID(); |
| 767 | 771 | ReceiveTask receiveTask = new ReceiveTask(); |
| 768 | 772 | receiveTask.setId(attachNodeId); |
| 769 | 773 | receiveTask.setName("异步 HTTP 请求"); |
| 770 | 774 | node.setAttachNodeId(attachNodeId); |
| 771 | - // 设置 receiveId | |
| 772 | - Assert.notNull(node.getTriggerSetting().getHttpRequestSetting(), "触发器 http 请求设置不能为空"); | |
| 773 | - node.getTriggerSetting().getHttpRequestSetting().setCallbackId(attachNodeId); | |
| 775 | + node.getTriggerSetting().getHttpRequestSetting().setCallbackId(attachNodeId); // 设置 receiveId | |
| 774 | 776 | flowElements.add(receiveTask); |
| 775 | 777 | } |
| 776 | 778 | |
| 779 | + // TODO @jason:是不是挪到 flowElements.add(serviceTask); 之前哈,因为它在处理 serviceTask | |
| 777 | 780 | if (node.getTriggerSetting().getHttpRequestSetting() != null) { |
| 778 | 781 | addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting()); |
| 779 | 782 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
| ... | ... | @@ -276,8 +276,9 @@ public interface BpmTaskService { |
| 276 | 276 | */ |
| 277 | 277 | void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer handlerType); |
| 278 | 278 | |
| 279 | + // TODO @jason:改成 triggerTask。然后,“触发 ReceiveTask,让流程继续执行”,改成一些调用场景 | |
| 279 | 280 | /** |
| 280 | - * 触发 ReceiveTask, 让流程继续执行 | |
| 281 | + * 触发 ReceiveTask,让流程继续执行 | |
| 281 | 282 | * |
| 282 | 283 | * @param processInstanceId 流程示例编号 |
| 283 | 284 | * @param taskDefineKey 任务 Key | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| ... | ... | @@ -1329,7 +1329,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 1329 | 1329 | .activityId(taskDefineKey) |
| 1330 | 1330 | .singleResult(); |
| 1331 | 1331 | if (execution == null) { |
| 1332 | - log.error("[processDelayTimerTimeout][processInstanceId({}) activityId({}) 没有找到执行活动]", | |
| 1332 | + log.error("[triggerReceiveTask][processInstanceId({}) activityId({}) 没有找到执行活动]", | |
| 1333 | 1333 | processInstanceId, taskDefineKey); |
| 1334 | 1334 | return; |
| 1335 | 1335 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormDeleteTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormDeleteTrigger.java
| 1 | -package cn.iocoder.yudao.module.bpm.service.task.trigger; | |
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger.form; | |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| ... | ... | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; |
| 7 | 7 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; |
| 8 | 8 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; |
| 9 | 9 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 10 | +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger; | |
| 10 | 11 | import com.fasterxml.jackson.core.type.TypeReference; |
| 11 | 12 | import jakarta.annotation.Resource; |
| 12 | 13 | import lombok.extern.slf4j.Slf4j; | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormUpdateTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormUpdateTrigger.java
| 1 | -package cn.iocoder.yudao.module.bpm.service.task.trigger; | |
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger.form; | |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| ... | ... | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; |
| 7 | 7 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; |
| 8 | 8 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; |
| 9 | 9 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 10 | +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger; | |
| 10 | 11 | import com.fasterxml.jackson.core.type.TypeReference; |
| 11 | 12 | import jakarta.annotation.Resource; |
| 12 | 13 | import lombok.extern.slf4j.Slf4j; | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmAbstractHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmAbstractHttpRequestTrigger.java
| 1 | -package cn.iocoder.yudao.module.bpm.service.task.trigger; | |
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger.http; | |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; |
| 4 | 4 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; |
| 5 | +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger; | |
| 5 | 6 | import jakarta.annotation.Resource; |
| 6 | 7 | import lombok.extern.slf4j.Slf4j; |
| 7 | 8 | import org.flowable.engine.runtime.ProcessInstance; |
| ... | ... | @@ -39,8 +40,7 @@ public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger { |
| 39 | 40 | HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); |
| 40 | 41 | ResponseEntity<String> responseEntity; |
| 41 | 42 | try { |
| 42 | - responseEntity = restTemplate.exchange(url, HttpMethod.POST, | |
| 43 | - requestEntity, String.class); | |
| 43 | + responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); | |
| 44 | 44 | log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); |
| 45 | 45 | } catch (RestClientException e) { |
| 46 | 46 | log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); |
| ... | ... | @@ -66,4 +66,5 @@ public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger { |
| 66 | 66 | body.add("processInstanceId", processInstance.getId()); |
| 67 | 67 | return body; |
| 68 | 68 | } |
| 69 | + | |
| 69 | 70 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmAsyncHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmAsyncHttpRequestTrigger.java
| 1 | -package cn.iocoder.yudao.module.bpm.service.task.trigger; | |
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger.http; | |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 4 | 4 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; |
| ... | ... | @@ -42,7 +42,8 @@ public class BpmAsyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { |
| 42 | 42 | MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader()); |
| 43 | 43 | // 2.2 设置请求体 |
| 44 | 44 | MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody()); |
| 45 | - body.add("callbackId", setting.getCallbackId()); // 异步请求 callbackId 需要传给被调用方. 用于回调执行 | |
| 45 | + // TODO @芋艿:【异步】在看看 | |
| 46 | + body.add("callbackId", setting.getCallbackId()); // 异步请求 callbackId 需要传给被调用方,用于回调执行 | |
| 46 | 47 | |
| 47 | 48 | // 3. 发起请求 |
| 48 | 49 | sendHttpRequest(setting.getUrl(), headers, body); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmSyncHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java