Commit 3f8221ba845420160107cfedac30745751e3fb69
1 parent
b88c09f4
【功能新增】 新增异步 http 请求触发器
Showing
11 changed files
with
211 additions
and
54 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java
| @@ -20,4 +20,12 @@ public interface BpmProcessInstanceApi { | @@ -20,4 +20,12 @@ public interface BpmProcessInstanceApi { | ||
| 20 | */ | 20 | */ |
| 21 | String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO); | 21 | String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO); |
| 22 | 22 | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 异步 HTTP 请求触发器回调, 为了唤醒流程继续执行 | ||
| 26 | + * | ||
| 27 | + * @param processInstanceId 流程实例编号 | ||
| 28 | + * @param callbackId 回调编号, 对应 ReceiveTask Id | ||
| 29 | + */ | ||
| 30 | + void asyncHttpTriggerCallback(String processInstanceId, String callbackId); | ||
| 23 | } | 31 | } |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java
| @@ -18,7 +18,8 @@ public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> { | @@ -18,7 +18,8 @@ public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> { | ||
| 18 | 18 | ||
| 19 | HTTP_REQUEST(1, "发起 HTTP 请求"), | 19 | HTTP_REQUEST(1, "发起 HTTP 请求"), |
| 20 | FORM_UPDATE(2, "更新流程表单数据"), | 20 | FORM_UPDATE(2, "更新流程表单数据"), |
| 21 | - FORM_DELETE(3, "删除流程表单数据"); | 21 | + FORM_DELETE(3, "删除流程表单数据"), |
| 22 | + ASYNC_HTTP_REQUEST(4, "发起异步 HTTP 请求"); | ||
| 22 | 23 | ||
| 23 | /** | 24 | /** |
| 24 | * 触发器执行动作类型 | 25 | * 触发器执行动作类型 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.api.task; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.api.task; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; | 3 | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| 4 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | 4 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 5 | +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; | ||
| 5 | import org.springframework.stereotype.Service; | 6 | import org.springframework.stereotype.Service; |
| 6 | import org.springframework.validation.annotation.Validated; | 7 | import org.springframework.validation.annotation.Validated; |
| 7 | 8 | ||
| @@ -21,8 +22,16 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi { | @@ -21,8 +22,16 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi { | ||
| 21 | @Resource | 22 | @Resource |
| 22 | private BpmProcessInstanceService processInstanceService; | 23 | private BpmProcessInstanceService processInstanceService; |
| 23 | 24 | ||
| 25 | + @Resource | ||
| 26 | + private BpmTaskService bpmTaskService; | ||
| 27 | + | ||
| 24 | @Override | 28 | @Override |
| 25 | public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO) { | 29 | public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO) { |
| 26 | return processInstanceService.createProcessInstance(userId, reqDTO); | 30 | return processInstanceService.createProcessInstance(userId, reqDTO); |
| 27 | } | 31 | } |
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public void asyncHttpTriggerCallback(String processInstanceId, String callbackId) { | ||
| 35 | + bpmTaskService.triggerReceiveTask(processInstanceId, callbackId); | ||
| 36 | + } | ||
| 28 | } | 37 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 4 | import cn.iocoder.yudao.framework.common.validation.InEnum; | 4 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 5 | import cn.iocoder.yudao.module.bpm.enums.definition.*; | 5 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; | 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; |
| 7 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 7 | import com.fasterxml.jackson.annotation.JsonInclude; | 8 | import com.fasterxml.jackson.annotation.JsonInclude; |
| 8 | import io.swagger.v3.oas.annotations.media.Schema; | 9 | import io.swagger.v3.oas.annotations.media.Schema; |
| 9 | import jakarta.validation.Valid; | 10 | import jakarta.validation.Valid; |
| @@ -123,6 +124,13 @@ public class BpmSimpleModelNodeVO { | @@ -123,6 +124,13 @@ public class BpmSimpleModelNodeVO { | ||
| 123 | */ | 124 | */ |
| 124 | private TriggerSetting triggerSetting; | 125 | private TriggerSetting triggerSetting; |
| 125 | 126 | ||
| 127 | + /** | ||
| 128 | + * 附加节点 Id, 该节点不从前端传入。 由程序生成. 由于当个节点无法完成功能。 需要附加节点来完成。 | ||
| 129 | + */ | ||
| 130 | + @JsonIgnore | ||
| 131 | + private String attachNodeId; // 目前用于异步触发器节点。需要 UserTask 和 ReceiveTask(附加节点) 来完成 | ||
| 132 | + | ||
| 133 | + | ||
| 126 | @Schema(description = "任务监听器") | 134 | @Schema(description = "任务监听器") |
| 127 | @Valid | 135 | @Valid |
| 128 | @Data | 136 | @Data |
| @@ -378,6 +386,10 @@ public class BpmSimpleModelNodeVO { | @@ -378,6 +386,10 @@ public class BpmSimpleModelNodeVO { | ||
| 378 | @Schema(description = "请求返回处理设置", example = "[]") | 386 | @Schema(description = "请求返回处理设置", example = "[]") |
| 379 | private List<KeyValue<String, String>> response; | 387 | private List<KeyValue<String, String>> response; |
| 380 | 388 | ||
| 389 | + /** | ||
| 390 | + * 异步 Http 请求,需要指定回调 Id,用于回调执行. 由后端指定 | ||
| 391 | + */ | ||
| 392 | + private String callbackId; | ||
| 381 | } | 393 | } |
| 382 | 394 | ||
| 383 | @Schema(description = "流程表单触发器设置", example = "{}") | 395 | @Schema(description = "流程表单触发器设置", example = "{}") |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
| @@ -109,8 +109,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { | @@ -109,8 +109,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { | ||
| 109 | // 2.2 延迟器超时处理 | 109 | // 2.2 延迟器超时处理 |
| 110 | } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT)) { | 110 | } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT)) { |
| 111 | String taskKey = boundaryEvent.getAttachedToRefId(); | 111 | String taskKey = boundaryEvent.getAttachedToRefId(); |
| 112 | - taskService.processDelayTimerTimeout(event.getProcessInstanceId(), taskKey); | 112 | + taskService.triggerReceiveTask(event.getProcessInstanceId(), taskKey); |
| 113 | } | 113 | } |
| 114 | } | 114 | } |
| 115 | - | ||
| 116 | } | 115 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| @@ -21,6 +21,7 @@ import org.springframework.util.MultiValueMap; | @@ -21,6 +21,7 @@ import org.springframework.util.MultiValueMap; | ||
| 21 | 21 | ||
| 22 | import java.util.*; | 22 | import java.util.*; |
| 23 | 23 | ||
| 24 | +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum.ASYNC_HTTP_REQUEST; | ||
| 24 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; | 25 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; |
| 25 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; | 26 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; |
| 26 | import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION; | 27 | import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION; |
| @@ -164,8 +165,15 @@ public class SimpleModelUtils { | @@ -164,8 +165,15 @@ public class SimpleModelUtils { | ||
| 164 | // 情况一:有“子”节点,则建立连线 | 165 | // 情况一:有“子”节点,则建立连线 |
| 165 | // 情况二:没有“子节点”,则直接跟 targetNodeId 建立连线。例如说,结束节点、条件分支(分支节点的孩子节点或聚合节点)的最后一个节点 | 166 | // 情况二:没有“子节点”,则直接跟 targetNodeId 建立连线。例如说,结束节点、条件分支(分支节点的孩子节点或聚合节点)的最后一个节点 |
| 166 | String finalTargetNodeId = isChildNodeValid ? childNode.getId() : targetNodeId; | 167 | String finalTargetNodeId = isChildNodeValid ? childNode.getId() : targetNodeId; |
| 167 | - SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), finalTargetNodeId); | ||
| 168 | - process.addFlowElement(sequenceFlow); | 168 | + |
| 169 | + if (StrUtil.isEmpty(node.getAttachNodeId())) { | ||
| 170 | + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), finalTargetNodeId); | ||
| 171 | + process.addFlowElement(sequenceFlow); | ||
| 172 | + } else { | ||
| 173 | + // 如果有附加节点. 需要先建立和附加节点的连线。再建立附加节点和目标节点的连线 | ||
| 174 | + List<SequenceFlow> sequenceFlows = buildAttachNodeSequenceFlow(node.getId(), node.getAttachNodeId(), finalTargetNodeId); | ||
| 175 | + sequenceFlows.forEach(process::addFlowElement); | ||
| 176 | + } | ||
| 169 | 177 | ||
| 170 | // 因为有子节点,递归调用后续子节点 | 178 | // 因为有子节点,递归调用后续子节点 |
| 171 | if (isChildNodeValid) { | 179 | if (isChildNodeValid) { |
| @@ -174,6 +182,19 @@ public class SimpleModelUtils { | @@ -174,6 +182,19 @@ public class SimpleModelUtils { | ||
| 174 | } | 182 | } |
| 175 | 183 | ||
| 176 | /** | 184 | /** |
| 185 | + * 构建有附加节点的连线 | ||
| 186 | + * | ||
| 187 | + * @param nodeId 当前节点 Id | ||
| 188 | + * @param attachNodeId 附属节点 Id | ||
| 189 | + * @param targetNodeId 目标节点 Id | ||
| 190 | + */ | ||
| 191 | + private static List<SequenceFlow> buildAttachNodeSequenceFlow(String nodeId, String attachNodeId, String targetNodeId) { | ||
| 192 | + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(nodeId, attachNodeId, null, null, null); | ||
| 193 | + SequenceFlow attachSequenceFlow = buildBpmnSequenceFlow(attachNodeId, targetNodeId, null, null, null); | ||
| 194 | + return CollUtil.newArrayList(sequenceFlow, attachSequenceFlow); | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + /** | ||
| 177 | * 遍历条件节点,构建 SequenceFlow 元素 | 198 | * 遍历条件节点,构建 SequenceFlow 元素 |
| 178 | * | 199 | * |
| 179 | * @param process Bpmn 流程 | 200 | * @param process Bpmn 流程 |
| @@ -723,23 +744,38 @@ public class SimpleModelUtils { | @@ -723,23 +744,38 @@ public class SimpleModelUtils { | ||
| 723 | public static class TriggerNodeConvert implements NodeConvert { | 744 | public static class TriggerNodeConvert implements NodeConvert { |
| 724 | 745 | ||
| 725 | @Override | 746 | @Override |
| 726 | - public ServiceTask convert(BpmSimpleModelNodeVO node) { | 747 | + public List<? extends FlowElement> convertList(BpmSimpleModelNodeVO node) { |
| 748 | + List<FlowElement> flowElements = new ArrayList<>(2); | ||
| 727 | // 触发器使用 ServiceTask 来实现 | 749 | // 触发器使用 ServiceTask 来实现 |
| 728 | ServiceTask serviceTask = new ServiceTask(); | 750 | ServiceTask serviceTask = new ServiceTask(); |
| 729 | serviceTask.setId(node.getId()); | 751 | serviceTask.setId(node.getId()); |
| 730 | serviceTask.setName(node.getName()); | 752 | serviceTask.setName(node.getName()); |
| 731 | serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); | 753 | serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); |
| 732 | serviceTask.setImplementation("${" + BpmTriggerTaskDelegate.BEAN_NAME + "}"); | 754 | serviceTask.setImplementation("${" + BpmTriggerTaskDelegate.BEAN_NAME + "}"); |
| 733 | - if (node.getTriggerSetting() != null) { | ||
| 734 | - addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType()); | ||
| 735 | - if (node.getTriggerSetting().getHttpRequestSetting() != null) { | ||
| 736 | - addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting()); | ||
| 737 | - } | ||
| 738 | - if (node.getTriggerSetting().getFormSettings() != null) { | ||
| 739 | - addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getFormSettings()); | ||
| 740 | - } | 755 | + Assert.notNull(node.getTriggerSetting(), "触发器节点设置不能为空"); |
| 756 | + | ||
| 757 | + addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType()); | ||
| 758 | + flowElements.add(serviceTask); | ||
| 759 | + // 异步 HTTP 请求。需要附加一个 ReceiveTask、发起请求后、等待回调执行 | ||
| 760 | + if (ASYNC_HTTP_REQUEST.getType().equals(node.getTriggerSetting().getType())) { | ||
| 761 | + String attachNodeId = "Activity_" + IdUtil.fastUUID(); | ||
| 762 | + ReceiveTask receiveTask = new ReceiveTask(); | ||
| 763 | + receiveTask.setId(attachNodeId); | ||
| 764 | + receiveTask.setName("异步 HTTP 请求"); | ||
| 765 | + node.setAttachNodeId(attachNodeId); | ||
| 766 | + // 设置 receiveId | ||
| 767 | + Assert.notNull(node.getTriggerSetting().getHttpRequestSetting(), "触发器 http 请求设置不能为空"); | ||
| 768 | + node.getTriggerSetting().getHttpRequestSetting().setCallbackId(attachNodeId); | ||
| 769 | + flowElements.add(receiveTask); | ||
| 741 | } | 770 | } |
| 742 | - return serviceTask; | 771 | + |
| 772 | + if (node.getTriggerSetting().getHttpRequestSetting() != null) { | ||
| 773 | + addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting()); | ||
| 774 | + } | ||
| 775 | + if (node.getTriggerSetting().getFormSettings() != null) { | ||
| 776 | + addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getFormSettings()); | ||
| 777 | + } | ||
| 778 | + return flowElements; | ||
| 743 | } | 779 | } |
| 744 | 780 | ||
| 745 | @Override | 781 | @Override |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
| @@ -277,11 +277,11 @@ public interface BpmTaskService { | @@ -277,11 +277,11 @@ public interface BpmTaskService { | ||
| 277 | void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer handlerType); | 277 | void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer handlerType); |
| 278 | 278 | ||
| 279 | /** | 279 | /** |
| 280 | - * 处理 延迟器 超时事件 | 280 | + * 触发 ReceiveTask, 让流程继续执行 |
| 281 | * | 281 | * |
| 282 | * @param processInstanceId 流程示例编号 | 282 | * @param processInstanceId 流程示例编号 |
| 283 | * @param taskDefineKey 任务 Key | 283 | * @param taskDefineKey 任务 Key |
| 284 | */ | 284 | */ |
| 285 | - void processDelayTimerTimeout(String processInstanceId, String taskDefineKey); | 285 | + void triggerReceiveTask(String processInstanceId, String taskDefineKey); |
| 286 | 286 | ||
| 287 | } | 287 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -1309,7 +1309,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -1309,7 +1309,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 1309 | } | 1309 | } |
| 1310 | 1310 | ||
| 1311 | @Override | 1311 | @Override |
| 1312 | - public void processDelayTimerTimeout(String processInstanceId, String taskDefineKey) { | 1312 | + public void triggerReceiveTask(String processInstanceId, String taskDefineKey) { |
| 1313 | Execution execution = runtimeService.createExecutionQuery() | 1313 | Execution execution = runtimeService.createExecutionQuery() |
| 1314 | .processInstanceId(processInstanceId) | 1314 | .processInstanceId(processInstanceId) |
| 1315 | .activityId(taskDefineKey) | 1315 | .activityId(taskDefineKey) |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmAbstractHttpRequestTrigger.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; | ||
| 5 | +import jakarta.annotation.Resource; | ||
| 6 | +import lombok.extern.slf4j.Slf4j; | ||
| 7 | +import org.flowable.engine.runtime.ProcessInstance; | ||
| 8 | +import org.springframework.http.HttpEntity; | ||
| 9 | +import org.springframework.http.HttpMethod; | ||
| 10 | +import org.springframework.http.ResponseEntity; | ||
| 11 | +import org.springframework.util.LinkedMultiValueMap; | ||
| 12 | +import org.springframework.util.MultiValueMap; | ||
| 13 | +import org.springframework.web.client.RestClientException; | ||
| 14 | +import org.springframework.web.client.RestTemplate; | ||
| 15 | + | ||
| 16 | +import java.util.List; | ||
| 17 | +import java.util.Map; | ||
| 18 | + | ||
| 19 | +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * BPM 发送 HTTP 请求触发器抽象类 | ||
| 23 | + * | ||
| 24 | + * @author jason | ||
| 25 | + */ | ||
| 26 | +@Slf4j | ||
| 27 | +public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger { | ||
| 28 | + | ||
| 29 | + @Resource | ||
| 30 | + private RestTemplate restTemplate; | ||
| 31 | + | ||
| 32 | + protected ResponseEntity<String> sendHttpRequest(String url, | ||
| 33 | + MultiValueMap<String, String> headers, | ||
| 34 | + MultiValueMap<String, String> body) { | ||
| 35 | + // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢? | ||
| 36 | + // 3. 发起请求 | ||
| 37 | + HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); | ||
| 38 | + ResponseEntity<String> responseEntity = null; | ||
| 39 | + try { | ||
| 40 | + responseEntity = restTemplate.exchange(url, HttpMethod.POST, | ||
| 41 | + requestEntity, String.class); | ||
| 42 | + log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); | ||
| 43 | + } catch (RestClientException e) { | ||
| 44 | + log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); | ||
| 45 | + } | ||
| 46 | + return responseEntity; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + protected MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance, | ||
| 50 | + List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) { | ||
| 51 | + Map<String, Object> processVariables = processInstance.getProcessVariables(); | ||
| 52 | + MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); | ||
| 53 | + headers.add(HEADER_TENANT_ID, processInstance.getTenantId()); | ||
| 54 | + SimpleModelUtils.addHttpRequestParam(headers, headerSettings, processVariables); | ||
| 55 | + return headers; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + protected MultiValueMap<String, String> buildHttpBody(ProcessInstance processInstance, | ||
| 59 | + List<BpmSimpleModelNodeVO.HttpRequestParam> bodySettings) { | ||
| 60 | + Map<String, Object> processVariables = processInstance.getProcessVariables(); | ||
| 61 | + MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); | ||
| 62 | + SimpleModelUtils.addHttpRequestParam(body, bodySettings, processVariables); | ||
| 63 | + body.add("processInstanceId", processInstance.getId()); | ||
| 64 | + return body; | ||
| 65 | + } | ||
| 66 | +} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmAsyncHttpRequestTrigger.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||
| 7 | +import jakarta.annotation.Resource; | ||
| 8 | +import lombok.extern.slf4j.Slf4j; | ||
| 9 | +import org.flowable.engine.runtime.ProcessInstance; | ||
| 10 | +import org.springframework.stereotype.Component; | ||
| 11 | +import org.springframework.util.MultiValueMap; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * BPM 发送异步 HTTP 请求触发器 | ||
| 15 | + * | ||
| 16 | + * @author jason | ||
| 17 | + */ | ||
| 18 | +@Component | ||
| 19 | +@Slf4j | ||
| 20 | +public class BpmAsyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { | ||
| 21 | + | ||
| 22 | + @Resource | ||
| 23 | + private BpmProcessInstanceService processInstanceService; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public BpmTriggerTypeEnum getType() { | ||
| 27 | + return BpmTriggerTypeEnum.ASYNC_HTTP_REQUEST; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public void execute(String processInstanceId, String param) { | ||
| 32 | + // 1. 解析 http 请求配置 | ||
| 33 | + BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting setting = JsonUtils.parseObject(param, | ||
| 34 | + BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting.class); | ||
| 35 | + if (setting == null) { | ||
| 36 | + log.error("[execute][流程({}) HTTP 异步触发器请求配置为空]", processInstanceId); | ||
| 37 | + return; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + // 2.1 设置请求头 | ||
| 41 | + ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); | ||
| 42 | + MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader()); | ||
| 43 | + // 2.2 设置请求体 | ||
| 44 | + MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody()); | ||
| 45 | + body.add("callbackId", setting.getCallbackId()); // 异步请求 callbackId 需要传给被调用方. 用于回调执行 | ||
| 46 | + | ||
| 47 | + // 3. 发起请求 | ||
| 48 | + sendHttpRequest(setting.getUrl(), headers, body); | ||
| 49 | + } | ||
| 50 | +} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmSyncHttpRequestTrigger.java
| @@ -7,42 +7,31 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | @@ -7,42 +7,31 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 8 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting; | 8 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting; |
| 9 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; | 9 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; |
| 10 | -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; | ||
| 11 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | 10 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 12 | import com.fasterxml.jackson.core.type.TypeReference; | 11 | import com.fasterxml.jackson.core.type.TypeReference; |
| 13 | import jakarta.annotation.Resource; | 12 | import jakarta.annotation.Resource; |
| 14 | import lombok.extern.slf4j.Slf4j; | 13 | import lombok.extern.slf4j.Slf4j; |
| 15 | import org.flowable.engine.runtime.ProcessInstance; | 14 | import org.flowable.engine.runtime.ProcessInstance; |
| 16 | -import org.springframework.http.HttpEntity; | ||
| 17 | -import org.springframework.http.HttpMethod; | ||
| 18 | import org.springframework.http.ResponseEntity; | 15 | import org.springframework.http.ResponseEntity; |
| 19 | import org.springframework.stereotype.Component; | 16 | import org.springframework.stereotype.Component; |
| 20 | -import org.springframework.util.LinkedMultiValueMap; | ||
| 21 | import org.springframework.util.MultiValueMap; | 17 | import org.springframework.util.MultiValueMap; |
| 22 | -import org.springframework.web.client.RestClientException; | ||
| 23 | -import org.springframework.web.client.RestTemplate; | ||
| 24 | 18 | ||
| 25 | import java.util.HashMap; | 19 | import java.util.HashMap; |
| 26 | import java.util.List; | 20 | import java.util.List; |
| 27 | import java.util.Map; | 21 | import java.util.Map; |
| 28 | 22 | ||
| 29 | -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; | ||
| 30 | - | ||
| 31 | /** | 23 | /** |
| 32 | - * BPM 发送 HTTP 请求触发器 | 24 | + * BPM 发送同步 HTTP 请求触发器 |
| 33 | * | 25 | * |
| 34 | * @author jason | 26 | * @author jason |
| 35 | */ | 27 | */ |
| 36 | @Component | 28 | @Component |
| 37 | @Slf4j | 29 | @Slf4j |
| 38 | -public class BpmHttpRequestTrigger implements BpmTrigger { | 30 | +public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { |
| 39 | 31 | ||
| 40 | @Resource | 32 | @Resource |
| 41 | private BpmProcessInstanceService processInstanceService; | 33 | private BpmProcessInstanceService processInstanceService; |
| 42 | 34 | ||
| 43 | - @Resource | ||
| 44 | - private RestTemplate restTemplate; | ||
| 45 | - | ||
| 46 | @Override | 35 | @Override |
| 47 | public BpmTriggerTypeEnum getType() { | 36 | public BpmTriggerTypeEnum getType() { |
| 48 | return BpmTriggerTypeEnum.HTTP_REQUEST; | 37 | return BpmTriggerTypeEnum.HTTP_REQUEST; |
| @@ -56,40 +45,27 @@ public class BpmHttpRequestTrigger implements BpmTrigger { | @@ -56,40 +45,27 @@ public class BpmHttpRequestTrigger implements BpmTrigger { | ||
| 56 | log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId); | 45 | log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId); |
| 57 | return; | 46 | return; |
| 58 | } | 47 | } |
| 48 | + | ||
| 59 | // 2.1 设置请求头 | 49 | // 2.1 设置请求头 |
| 60 | ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); | 50 | ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); |
| 61 | - Map<String, Object> processVariables = processInstance.getProcessVariables(); | ||
| 62 | - MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); | ||
| 63 | - headers.add(HEADER_TENANT_ID, processInstance.getTenantId()); | ||
| 64 | - SimpleModelUtils.addHttpRequestParam(headers, setting.getHeader(), processVariables); | 51 | + MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader()); |
| 65 | // 2.2 设置请求体 | 52 | // 2.2 设置请求体 |
| 66 | - MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); | ||
| 67 | - SimpleModelUtils.addHttpRequestParam(body, setting.getBody(), processVariables); | ||
| 68 | - body.add("processInstanceId", processInstanceId); | 53 | + MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody()); |
| 69 | 54 | ||
| 70 | - // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢? | ||
| 71 | // 3. 发起请求 | 55 | // 3. 发起请求 |
| 72 | - HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); | ||
| 73 | - ResponseEntity<String> responseEntity; | ||
| 74 | - try { | ||
| 75 | - responseEntity = restTemplate.exchange(setting.getUrl(), HttpMethod.POST, | ||
| 76 | - requestEntity, String.class); | ||
| 77 | - log.info("[execute][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); | ||
| 78 | - } catch (RestClientException e) { | ||
| 79 | - log.error("[execute][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); | ||
| 80 | - return; | ||
| 81 | - } | 56 | + ResponseEntity<String> responseEntity = sendHttpRequest(setting.getUrl(), headers, body); |
| 82 | 57 | ||
| 83 | // 4.1 判断是否需要解析返回值 | 58 | // 4.1 判断是否需要解析返回值 |
| 84 | - if (StrUtil.isEmpty(responseEntity.getBody()) | 59 | + if (responseEntity == null || StrUtil.isEmpty(responseEntity.getBody()) |
| 85 | || !responseEntity.getStatusCode().is2xxSuccessful() | 60 | || !responseEntity.getStatusCode().is2xxSuccessful() |
| 86 | || CollUtil.isEmpty(setting.getResponse())) { | 61 | || CollUtil.isEmpty(setting.getResponse())) { |
| 87 | return; | 62 | return; |
| 88 | } | 63 | } |
| 89 | // 4.2 解析返回值, 返回值必须符合 CommonResult 规范。 | 64 | // 4.2 解析返回值, 返回值必须符合 CommonResult 规范。 |
| 90 | CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly( | 65 | CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly( |
| 91 | - responseEntity.getBody(), new TypeReference<>() {}); | ||
| 92 | - if (respResult == null || !respResult.isSuccess()){ | 66 | + responseEntity.getBody(), new TypeReference<>() { |
| 67 | + }); | ||
| 68 | + if (respResult == null || !respResult.isSuccess()) { | ||
| 93 | return; | 69 | return; |
| 94 | } | 70 | } |
| 95 | // 4.3 获取需要更新的流程变量 | 71 | // 4.3 获取需要更新的流程变量 |
| @@ -103,11 +79,11 @@ public class BpmHttpRequestTrigger implements BpmTrigger { | @@ -103,11 +79,11 @@ public class BpmHttpRequestTrigger implements BpmTrigger { | ||
| 103 | /** | 79 | /** |
| 104 | * 从请求返回值获取需要更新的流程变量 | 80 | * 从请求返回值获取需要更新的流程变量 |
| 105 | * | 81 | * |
| 106 | - * @param result 请求返回结果 | 82 | + * @param result 请求返回结果 |
| 107 | * @param responseSettings 返回设置 | 83 | * @param responseSettings 返回设置 |
| 108 | * @return 需要更新的流程变量 | 84 | * @return 需要更新的流程变量 |
| 109 | */ | 85 | */ |
| 110 | - private Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String,Object> result, | 86 | + private Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String, Object> result, |
| 111 | List<KeyValue<String, String>> responseSettings) { | 87 | List<KeyValue<String, String>> responseSettings) { |
| 112 | Map<String, Object> updateVariables = new HashMap<>(); | 88 | Map<String, Object> updateVariables = new HashMap<>(); |
| 113 | if (CollUtil.isEmpty(result)) { | 89 | if (CollUtil.isEmpty(result)) { |