Commit e114a354513140820e3d9add68d22804217a54a6

Authored by Lesan
1 parent 24261cf7

feat: 流程前后置通知

Showing 11 changed files with 348 additions and 224 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
1 package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; 1 package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
2 2
  3 +import cn.iocoder.yudao.framework.common.core.KeyValue;
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
4 import cn.iocoder.yudao.module.bpm.enums.definition.BpmAutoApproveTypeEnum; 6 import cn.iocoder.yudao.module.bpm.enums.definition.BpmAutoApproveTypeEnum;
5 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; 7 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
6 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum; 8 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
@@ -80,6 +82,12 @@ public class BpmModelMetaInfoVO { @@ -80,6 +82,12 @@ public class BpmModelMetaInfoVO {
80 @Schema(description = "摘要设置", example = "{}") 82 @Schema(description = "摘要设置", example = "{}")
81 private SummarySetting summarySetting; 83 private SummarySetting summarySetting;
82 84
  85 + @Schema(description = "流程前置通知设置", example = "{}")
  86 + private HttpRequestSetting PreProcessNotifySetting;
  87 +
  88 + @Schema(description = "流程后置通知设置", example = "{}")
  89 + private HttpRequestSetting PostProcessNotifySetting;
  90 +
83 @Schema(description = "流程 ID 规则") 91 @Schema(description = "流程 ID 规则")
84 @Data 92 @Data
85 @Valid 93 @Valid
@@ -132,4 +140,32 @@ public class BpmModelMetaInfoVO { @@ -132,4 +140,32 @@ public class BpmModelMetaInfoVO {
132 140
133 } 141 }
134 142
  143 + @Schema(description = "http 请求通知设置", example = "{}")
  144 + @Data
  145 + public static class HttpRequestSetting {
  146 +
  147 + @Schema(description = "请求路径", example = "http://127.0.0.1")
  148 + @NotEmpty(message = "请求 URL 不能为空")
  149 + @URL(message = "请求 URL 格式不正确")
  150 + private String url;
  151 +
  152 + @Schema(description = "请求头参数设置", example = "[]")
  153 + @Valid
  154 + private List<BpmSimpleModelNodeVO.HttpRequestParam> header;
  155 +
  156 + @Schema(description = "请求头参数设置", example = "[]")
  157 + @Valid
  158 + private List<BpmSimpleModelNodeVO.HttpRequestParam> body;
  159 +
  160 + /**
  161 + * 请求返回处理设置,用于修改流程表单值
  162 + * <p>
  163 + * key:表示要修改的流程表单字段名(name)
  164 + * value:接口返回的字段名
  165 + */
  166 + @Schema(description = "请求返回处理设置", example = "[]")
  167 + private List<KeyValue<String, String>> response;
  168 +
  169 + }
  170 +
135 } 171 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java
@@ -189,4 +189,16 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { @@ -189,4 +189,16 @@ public class BpmProcessDefinitionInfoDO extends BaseDO {
189 @TableField(typeHandler = JacksonTypeHandler.class) 189 @TableField(typeHandler = JacksonTypeHandler.class)
190 private BpmModelMetaInfoVO.SummarySetting summarySetting; 190 private BpmModelMetaInfoVO.SummarySetting summarySetting;
191 191
  192 + /**
  193 + * 流程前置通知设置
  194 + */
  195 + @TableField(typeHandler = JacksonTypeHandler.class)
  196 + private BpmModelMetaInfoVO.HttpRequestSetting PreProcessNotifySetting;
  197 +
  198 + /**
  199 + * 流程后置通知设置
  200 + */
  201 + @TableField(typeHandler = JacksonTypeHandler.class)
  202 + private BpmModelMetaInfoVO.HttpRequestSetting PostProcessNotifySetting;
  203 +
192 } 204 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
@@ -22,6 +22,7 @@ import java.util.Set; @@ -22,6 +22,7 @@ import java.util.Set;
22 public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener { 22 public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
23 23
24 public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder() 24 public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
  25 + .add(FlowableEngineEventType.PROCESS_CREATED)
25 .add(FlowableEngineEventType.PROCESS_COMPLETED) 26 .add(FlowableEngineEventType.PROCESS_COMPLETED)
26 .add(FlowableEngineEventType.PROCESS_CANCELLED) 27 .add(FlowableEngineEventType.PROCESS_CANCELLED)
27 .build(); 28 .build();
@@ -35,6 +36,11 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent @@ -35,6 +36,11 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
35 } 36 }
36 37
37 @Override 38 @Override
  39 + protected void processCreated(FlowableEngineEntityEvent event) {
  40 + processInstanceService.processProcessInstanceCreated((ProcessInstance)event.getEntity());
  41 + }
  42 +
  43 + @Override
38 protected void processCompleted(FlowableEngineEntityEvent event) { 44 protected void processCompleted(FlowableEngineEntityEvent event) {
39 processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity()); 45 processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity());
40 } 46 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.core.KeyValue;
  6 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  7 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  9 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
  10 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  11 +import com.fasterxml.jackson.core.type.TypeReference;
  12 +import lombok.extern.slf4j.Slf4j;
  13 +import org.flowable.engine.runtime.ProcessInstance;
  14 +import org.springframework.http.HttpEntity;
  15 +import org.springframework.http.HttpMethod;
  16 +import org.springframework.http.ResponseEntity;
  17 +import org.springframework.util.LinkedMultiValueMap;
  18 +import org.springframework.util.MultiValueMap;
  19 +import org.springframework.web.client.RestClientException;
  20 +import org.springframework.web.client.RestTemplate;
  21 +
  22 +import java.util.HashMap;
  23 +import java.util.List;
  24 +import java.util.Map;
  25 +
  26 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  27 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  28 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR;
  29 +
  30 +/**
  31 + * 工作流发起 HTTP 请求工具类
  32 + *
  33 + * @author 芋道源码
  34 + */
  35 +@Slf4j
  36 +public class BpmHttpRequestUtils {
  37 +
  38 + public static void executeBpmHttpRequest(ProcessInstance processInstance,
  39 + String url,
  40 + List<BpmSimpleModelNodeVO.HttpRequestParam> headerParam,
  41 + List<BpmSimpleModelNodeVO.HttpRequestParam> bodyParam,
  42 + Boolean handleResponse,
  43 + List<KeyValue<String, String>> response,
  44 + RestTemplate restTemplate,
  45 + BpmProcessInstanceService processInstanceService) {
  46 +
  47 + // 1.1 设置请求头
  48 + MultiValueMap<String, String> headers = BpmHttpRequestUtils.buildHttpHeaders(processInstance, headerParam);
  49 + // 1.2 设置请求体
  50 + MultiValueMap<String, String> body = BpmHttpRequestUtils.buildHttpBody(processInstance, bodyParam);
  51 +
  52 + // 2. 发起请求
  53 + ResponseEntity<String> responseEntity = BpmHttpRequestUtils.sendHttpRequest(url, headers, body, restTemplate);
  54 +
  55 + // 3. 处理返回
  56 + if (Boolean.TRUE.equals(handleResponse)) {
  57 + // 3.1 判断是否需要解析返回值
  58 + if (responseEntity == null || StrUtil.isEmpty(responseEntity.getBody())
  59 + || !responseEntity.getStatusCode().is2xxSuccessful()
  60 + || CollUtil.isEmpty(response)) {
  61 + return;
  62 + }
  63 + // 3.2 解析返回值, 返回值必须符合 CommonResult 规范。
  64 + CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly(
  65 + responseEntity.getBody(), new TypeReference<>() {
  66 + });
  67 + if (respResult == null || !respResult.isSuccess()) {
  68 + return;
  69 + }
  70 + // 3.3 获取需要更新的流程变量
  71 + Map<String, Object> updateVariables = BpmHttpRequestUtils.getNeedUpdatedVariablesFromResponse(respResult.getData(), response);
  72 + // 3.4 更新流程变量
  73 + if (CollUtil.isNotEmpty(updateVariables)) {
  74 + processInstanceService.updateProcessInstanceVariables(processInstance.getId(), updateVariables);
  75 + }
  76 + }
  77 +
  78 + }
  79 +
  80 + public static ResponseEntity<String> sendHttpRequest(String url,
  81 + MultiValueMap<String, String> headers,
  82 + MultiValueMap<String, String> body,
  83 + RestTemplate restTemplate) {
  84 + // 3. 发起请求
  85 + HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
  86 + ResponseEntity<String> responseEntity;
  87 + try {
  88 + responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
  89 + log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
  90 + } catch (RestClientException e) {
  91 + log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
  92 + throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR);
  93 + }
  94 + return responseEntity;
  95 + }
  96 +
  97 + public static MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,
  98 + List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {
  99 + Map<String, Object> processVariables = processInstance.getProcessVariables();
  100 + MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
  101 + headers.add(HEADER_TENANT_ID, processInstance.getTenantId());
  102 + addHttpRequestParam(headers, headerSettings, processVariables);
  103 + return headers;
  104 + }
  105 +
  106 + public static MultiValueMap<String, String> buildHttpBody(ProcessInstance processInstance,
  107 + List<BpmSimpleModelNodeVO.HttpRequestParam> bodySettings) {
  108 + Map<String, Object> processVariables = processInstance.getProcessVariables();
  109 + MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
  110 + addHttpRequestParam(body, bodySettings, processVariables);
  111 + body.add("processInstanceId", processInstance.getId());
  112 + return body;
  113 + }
  114 +
  115 + /**
  116 + * 从请求返回值获取需要更新的流程变量
  117 + *
  118 + * @param result 请求返回结果
  119 + * @param responseSettings 返回设置
  120 + * @return 需要更新的流程变量
  121 + */
  122 + public static Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String, Object> result,
  123 + List<KeyValue<String, String>> responseSettings) {
  124 + Map<String, Object> updateVariables = new HashMap<>();
  125 + if (CollUtil.isEmpty(result)) {
  126 + return updateVariables;
  127 + }
  128 + responseSettings.forEach(responseSetting -> {
  129 + if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) {
  130 + updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue()));
  131 + }
  132 + });
  133 + return updateVariables;
  134 + }
  135 +
  136 + /**
  137 + * 添加 HTTP 请求参数。请求头或者请求体
  138 + *
  139 + * @param params HTTP 请求参数
  140 + * @param paramSettings HTTP 请求参数设置
  141 + * @param processVariables 流程变量
  142 + */
  143 + public static void addHttpRequestParam(MultiValueMap<String, String> params,
  144 + List<BpmSimpleModelNodeVO.HttpRequestParam> paramSettings,
  145 + Map<String, Object> processVariables) {
  146 + if (CollUtil.isEmpty(paramSettings)) {
  147 + return;
  148 + }
  149 + paramSettings.forEach(item -> {
  150 + if (item.getType().equals(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())) {
  151 + params.add(item.getKey(), item.getValue());
  152 + } else if (item.getType().equals(BpmHttpRequestParamTypeEnum.FROM_FORM.getType())) {
  153 + params.add(item.getKey(), processVariables.get(item.getValue()).toString());
  154 + }
  155 + });
  156 + }
  157 +
  158 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -21,7 +21,6 @@ import org.flowable.bpmn.model.Process; @@ -21,7 +21,6 @@ import org.flowable.bpmn.model.Process;
21 import org.flowable.bpmn.model.*; 21 import org.flowable.bpmn.model.*;
22 import org.flowable.engine.delegate.ExecutionListener; 22 import org.flowable.engine.delegate.ExecutionListener;
23 import org.flowable.engine.delegate.TaskListener; 23 import org.flowable.engine.delegate.TaskListener;
24 -import org.springframework.util.MultiValueMap;  
25 24
26 import java.util.*; 25 import java.util.*;
27 26
@@ -1002,27 +1001,4 @@ public class SimpleModelUtils { @@ -1002,27 +1001,4 @@ public class SimpleModelUtils {
1002 return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); 1001 return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
1003 } 1002 }
1004 1003
1005 - // TODO @芋艿:【高】要不要优化下,抽个 HttpUtils  
1006 -  
1007 - /**  
1008 - * 添加 HTTP 请求参数。请求头或者请求体  
1009 - *  
1010 - * @param params HTTP 请求参数  
1011 - * @param paramSettings HTTP 请求参数设置  
1012 - * @param processVariables 流程变量  
1013 - */  
1014 - public static void addHttpRequestParam(MultiValueMap<String, String> params,  
1015 - List<BpmSimpleModelNodeVO.HttpRequestParam> paramSettings,  
1016 - Map<String, Object> processVariables) {  
1017 - if (CollUtil.isEmpty(paramSettings)) {  
1018 - return;  
1019 - }  
1020 - paramSettings.forEach(item -> {  
1021 - if (item.getType().equals(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())) {  
1022 - params.add(item.getKey(), item.getValue());  
1023 - } else if (item.getType().equals(BpmHttpRequestParamTypeEnum.FROM_FORM.getType())) {  
1024 - params.add(item.getKey(), processVariables.get(item.getValue()).toString());  
1025 - }  
1026 - });  
1027 - }  
1028 } 1004 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
@@ -182,4 +182,10 @@ public interface BpmProcessInstanceService { @@ -182,4 +182,10 @@ public interface BpmProcessInstanceService {
182 */ 182 */
183 void processProcessInstanceCompleted(ProcessInstance instance); 183 void processProcessInstanceCompleted(ProcessInstance instance);
184 184
  185 + /**
  186 + * 处理 ProcessInstance 开始事件,例如说:流程前置通知
  187 + *
  188 + * @param instance 流程任务
  189 + */
  190 + void processProcessInstanceCreated(ProcessInstance instance);
185 } 191 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -34,6 +34,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidat @@ -34,6 +34,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidat
34 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; 34 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
35 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; 35 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
36 import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher; 36 import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
  37 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
37 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; 38 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
38 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; 39 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
39 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; 40 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
@@ -62,6 +63,7 @@ import org.springframework.context.annotation.Lazy; @@ -62,6 +63,7 @@ import org.springframework.context.annotation.Lazy;
62 import org.springframework.stereotype.Service; 63 import org.springframework.stereotype.Service;
63 import org.springframework.transaction.annotation.Transactional; 64 import org.springframework.transaction.annotation.Transactional;
64 import org.springframework.validation.annotation.Validated; 65 import org.springframework.validation.annotation.Validated;
  66 +import org.springframework.web.client.RestTemplate;
65 67
66 import java.util.*; 68 import java.util.*;
67 69
@@ -120,6 +122,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -120,6 +122,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
120 @Resource 122 @Resource
121 private BpmProcessIdRedisDAO processIdRedisDAO; 123 private BpmProcessIdRedisDAO processIdRedisDAO;
122 124
  125 + @Resource
  126 + private RestTemplate restTemplate;
  127 +
123 // ========== Query 查询相关方法 ========== 128 // ========== Query 查询相关方法 ==========
124 129
125 @Override 130 @Override
@@ -148,7 +153,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -148,7 +153,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
148 } 153 }
149 154
150 private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel, 155 private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel,
151 - String activityId, String taskId) { 156 + String activityId, String taskId) {
152 // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id 157 // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id
153 if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) { 158 if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) {
154 activityId = Optional.ofNullable(taskService.getHistoricTask(taskId)) 159 activityId = Optional.ofNullable(taskService.getHistoricTask(taskId))
@@ -351,15 +356,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -351,15 +356,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
351 * 主要是,拼接审批人的用户信息、部门信息 356 * 主要是,拼接审批人的用户信息、部门信息
352 */ 357 */
353 private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO, 358 private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO,
354 - BpmnModel bpmnModel,  
355 - ProcessDefinition processDefinition,  
356 - BpmProcessDefinitionInfoDO processDefinitionInfo,  
357 - HistoricProcessInstance processInstance,  
358 - Integer processInstanceStatus,  
359 - List<ActivityNode> endApprovalNodeInfos,  
360 - List<ActivityNode> runningApprovalNodeInfos,  
361 - List<ActivityNode> simulateApprovalNodeInfos,  
362 - BpmTaskRespVO todoTask) { 359 + BpmnModel bpmnModel,
  360 + ProcessDefinition processDefinition,
  361 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  362 + HistoricProcessInstance processInstance,
  363 + Integer processInstanceStatus,
  364 + List<ActivityNode> endApprovalNodeInfos,
  365 + List<ActivityNode> runningApprovalNodeInfos,
  366 + List<ActivityNode> simulateApprovalNodeInfos,
  367 + BpmTaskRespVO todoTask) {
363 // 1. 获取所有需要读取用户信息的 userIds 368 // 1. 获取所有需要读取用户信息的 userIds
364 List<ActivityNode> approveNodes = newArrayList( 369 List<ActivityNode> approveNodes = newArrayList(
365 asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos)); 370 asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos));
@@ -381,9 +386,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -381,9 +386,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
381 * 获得【已结束】的活动节点们 386 * 获得【已结束】的活动节点们
382 */ 387 */
383 private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel, 388 private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel,
384 - BpmProcessDefinitionInfoDO processDefinitionInfo,  
385 - HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus,  
386 - List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) { 389 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  390 + HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus,
  391 + List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) {
387 // 遍历 tasks 列表,只处理已结束的 UserTask 392 // 遍历 tasks 列表,只处理已结束的 UserTask
388 // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 393 // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities
389 // 的话,它无法成为一个节点 394 // 的话,它无法成为一个节点
@@ -451,11 +456,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -451,11 +456,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
451 * 获得【进行中】的活动节点们 456 * 获得【进行中】的活动节点们
452 */ 457 */
453 private List<ActivityNode> getRunApproveNodeList(Long startUserId, 458 private List<ActivityNode> getRunApproveNodeList(Long startUserId,
454 - BpmnModel bpmnModel,  
455 - ProcessDefinition processDefinition,  
456 - Map<String, Object> processVariables,  
457 - List<HistoricActivityInstance> activities,  
458 - List<HistoricTaskInstance> tasks) { 459 + BpmnModel bpmnModel,
  460 + ProcessDefinition processDefinition,
  461 + Map<String, Object> processVariables,
  462 + List<HistoricActivityInstance> activities,
  463 + List<HistoricTaskInstance> tasks) {
459 // 构建运行中的任务、子流程,基于 activityId 分组 464 // 构建运行中的任务、子流程,基于 activityId 分组
460 List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null 465 List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null
461 && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY))); 466 && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY)));
@@ -516,9 +521,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -516,9 +521,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
516 * 获得【预测(未来)】的活动节点们 521 * 获得【预测(未来)】的活动节点们
517 */ 522 */
518 private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel, 523 private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel,
519 - BpmProcessDefinitionInfoDO processDefinitionInfo,  
520 - Map<String, Object> processVariables,  
521 - List<HistoricActivityInstance> activities) { 524 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  525 + Map<String, Object> processVariables,
  526 + List<HistoricActivityInstance> activities) {
522 // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance 527 // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance
523 // 包括了历史的操作,不是只有 startEvent 到当前节点的记录 528 // 包括了历史的操作,不是只有 startEvent 到当前节点的记录
524 Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId); 529 Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId);
@@ -540,8 +545,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -540,8 +545,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
540 } 545 }
541 546
542 private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel, 547 private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel,
543 - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,  
544 - BpmSimpleModelNodeVO node, Set<String> runActivityIds) { 548 + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,
  549 + BpmSimpleModelNodeVO node, Set<String> runActivityIds) {
545 // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance 550 // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance
546 // 包括了历史的操作,不是只有 startEvent 到当前节点的记录 551 // 包括了历史的操作,不是只有 startEvent 到当前节点的记录
547 if (runActivityIds.contains(node.getId())) { 552 if (runActivityIds.contains(node.getId())) {
@@ -585,8 +590,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -585,8 +590,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
585 } 590 }
586 591
587 private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel, 592 private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel,
588 - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,  
589 - FlowElement node, Set<String> runActivityIds) { 593 + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,
  594 + FlowElement node, Set<String> runActivityIds) {
590 if (runActivityIds.contains(node.getId())) { 595 if (runActivityIds.contains(node.getId())) {
591 return null; 596 return null;
592 } 597 }
@@ -902,6 +907,46 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -902,6 +907,46 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
902 // 3. 发送流程实例的状态事件 907 // 3. 发送流程实例的状态事件
903 processInstanceEventPublisher.sendProcessInstanceResultEvent( 908 processInstanceEventPublisher.sendProcessInstanceResultEvent(
904 BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status)); 909 BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
  910 +
  911 + // 4. 流程后置通知
  912 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
  913 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
  914 + getProcessDefinitionInfo(instance.getProcessDefinitionId());
  915 + if (ObjUtil.isNotNull(processDefinitionInfo) &&
  916 + ObjUtil.isNotNull(processDefinitionInfo.getPostProcessNotifySetting())) {
  917 + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getPostProcessNotifySetting();
  918 +
  919 + BpmHttpRequestUtils.executeBpmHttpRequest(instance,
  920 + setting.getUrl(),
  921 + setting.getHeader(),
  922 + setting.getBody(),
  923 + true, setting.getResponse(),
  924 + restTemplate,
  925 + this);
  926 + }
  927 + }
  928 + });
  929 + }
  930 +
  931 + @Override
  932 + public void processProcessInstanceCreated(ProcessInstance instance) {
  933 + // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
  934 + FlowableUtils.execute(instance.getTenantId(), () -> {
  935 + // 流程前置通知
  936 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
  937 + getProcessDefinitionInfo(instance.getProcessDefinitionId());
  938 + if (ObjUtil.isNotNull(processDefinitionInfo) &&
  939 + ObjUtil.isNotNull(processDefinitionInfo.getPreProcessNotifySetting())) {
  940 + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getPreProcessNotifySetting();
  941 +
  942 + BpmHttpRequestUtils.executeBpmHttpRequest(instance,
  943 + setting.getUrl(),
  944 + setting.getHeader(),
  945 + setting.getBody(),
  946 + true, setting.getResponse(),
  947 + restTemplate,
  948 + this);
  949 + }
905 }); 950 });
906 } 951 }
907 } 952 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java
1 package cn.iocoder.yudao.module.bpm.service.task.listener; 1 package cn.iocoder.yudao.module.bpm.service.task.listener;
2 2
3 -import cn.hutool.core.util.StrUtil;  
4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; 3 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
5 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; 4 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
6 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 6 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
7 import jakarta.annotation.Resource; 7 import jakarta.annotation.Resource;
8 import lombok.Setter; 8 import lombok.Setter;
9 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
10 import org.flowable.engine.delegate.TaskListener; 10 import org.flowable.engine.delegate.TaskListener;
11 -import org.flowable.engine.history.HistoricProcessInstance;  
12 import org.flowable.engine.impl.el.FixedValue; 11 import org.flowable.engine.impl.el.FixedValue;
  12 +import org.flowable.engine.runtime.ProcessInstance;
13 import org.flowable.task.service.delegate.DelegateTask; 13 import org.flowable.task.service.delegate.DelegateTask;
14 import org.springframework.context.annotation.Scope; 14 import org.springframework.context.annotation.Scope;
15 -import org.springframework.http.HttpEntity;  
16 -import org.springframework.http.HttpMethod;  
17 -import org.springframework.http.ResponseEntity;  
18 import org.springframework.stereotype.Component; 15 import org.springframework.stereotype.Component;
19 -import org.springframework.util.LinkedMultiValueMap;  
20 -import org.springframework.util.MultiValueMap;  
21 -import org.springframework.web.client.RestClientException;  
22 import org.springframework.web.client.RestTemplate; 16 import org.springframework.web.client.RestTemplate;
23 17
24 -import java.util.Map;  
25 -  
26 -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;  
27 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseListenerConfig; 18 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseListenerConfig;
28 19
29 /** 20 /**
@@ -50,46 +41,35 @@ public class BpmUserTaskListener implements TaskListener { @@ -50,46 +41,35 @@ public class BpmUserTaskListener implements TaskListener {
50 @Override 41 @Override
51 public void notify(DelegateTask delegateTask) { 42 public void notify(DelegateTask delegateTask) {
52 // 1. 获取所需基础信息 43 // 1. 获取所需基础信息
53 - HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(delegateTask.getProcessInstanceId()); 44 + ProcessInstance processInstance = processInstanceService.getProcessInstance(delegateTask.getProcessInstanceId());
54 BpmSimpleModelNodeVO.ListenerHandler listenerHandler = parseListenerConfig(listenerConfig); 45 BpmSimpleModelNodeVO.ListenerHandler listenerHandler = parseListenerConfig(listenerConfig);
55 46
56 - // 2. 获取请求头和请求体  
57 - Map<String, Object> processVariables = processInstance.getProcessVariables();  
58 - MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();  
59 - MultiValueMap<String, String> body = new LinkedMultiValueMap<>();  
60 - SimpleModelUtils.addHttpRequestParam(headers, listenerHandler.getHeader(), processVariables);  
61 - SimpleModelUtils.addHttpRequestParam(body, listenerHandler.getBody(), processVariables);  
62 - // 2.1 请求头默认参数  
63 - if (StrUtil.isNotEmpty(delegateTask.getTenantId())) {  
64 - headers.add(HEADER_TENANT_ID, delegateTask.getTenantId());  
65 - }  
66 - // 2.2 请求体默认参数 47 + // 2. 发起请求
67 // TODO @芋艿:哪些默认参数,后续再调研下;感觉可以搞个 task 字段,把整个 delegateTask 放进去; 48 // TODO @芋艿:哪些默认参数,后续再调研下;感觉可以搞个 task 字段,把整个 delegateTask 放进去;
68 - body.add("processInstanceId", delegateTask.getProcessInstanceId());  
69 - body.add("assignee", delegateTask.getAssignee());  
70 - body.add("taskDefinitionKey", delegateTask.getTaskDefinitionKey());  
71 - body.add("taskId", delegateTask.getId()); 49 + listenerHandler.getBody()
  50 + .add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("processInstanceId")
  51 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
  52 + .setValue(delegateTask.getProcessInstanceId()));
  53 + listenerHandler.getBody()
  54 + .add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("assignee")
  55 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
  56 + .setValue(delegateTask.getAssignee()));
  57 + listenerHandler.getBody()
  58 + .add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskDefinitionKey")
  59 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
  60 + .setValue(delegateTask.getTaskDefinitionKey()));
  61 + listenerHandler.getBody()
  62 + .add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskId")
  63 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
  64 + .setValue(delegateTask.getId()));
  65 + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
  66 + listenerHandler.getPath(),
  67 + listenerHandler.getHeader(),
  68 + listenerHandler.getBody(),
  69 + false, null,
  70 + restTemplate,
  71 + processInstanceService);
72 72
73 - // 3. 异步发起请求  
74 - // TODO @芋艿:确认要同步,还是异步  
75 - HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);  
76 - try {  
77 - ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST,  
78 - requestEntity, String.class);  
79 - log.info("[notify][监听器:{},事件类型:{},请求头:{},请求体:{},响应结果:{}]",  
80 - DELEGATE_EXPRESSION,  
81 - delegateTask.getEventName(),  
82 - headers,  
83 - body,  
84 - responseEntity);  
85 - } catch (RestClientException e) {  
86 - log.error("[error][监听器:{},事件类型:{},请求头:{},请求体:{},请求出错:{}]",  
87 - DELEGATE_EXPRESSION,  
88 - delegateTask.getEventName(),  
89 - headers,  
90 - body,  
91 - e.getMessage());  
92 - }  
93 - // 4. 是否需要后续操作?TODO 芋艿:待定! 73 + // 3. 是否需要后续操作?TODO 芋艿:待定!
94 } 74 }
95 } 75 }
96 \ No newline at end of file 76 \ No newline at end of file
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.http; 1 package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2 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 cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger; 3 import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
6 -import jakarta.annotation.Resource;  
7 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
8 -import org.flowable.engine.runtime.ProcessInstance;  
9 -import org.springframework.http.HttpEntity;  
10 -import org.springframework.http.HttpMethod;  
11 -import org.springframework.http.ResponseEntity;  
12 -import org.springframework.util.LinkedMultiValueMap;  
13 -import org.springframework.util.MultiValueMap;  
14 -import org.springframework.web.client.RestClientException;  
15 -import org.springframework.web.client.RestTemplate;  
16 -  
17 -import java.util.List;  
18 -import java.util.Map;  
19 -  
20 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
21 -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;  
22 -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR;  
23 5
24 /** 6 /**
25 * BPM 发送 HTTP 请求触发器抽象类 7 * BPM 发送 HTTP 请求触发器抽象类
@@ -29,42 +11,4 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTA @@ -29,42 +11,4 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTA
29 @Slf4j 11 @Slf4j
30 public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger { 12 public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger {
31 13
32 - @Resource  
33 - private RestTemplate restTemplate;  
34 -  
35 - protected ResponseEntity<String> sendHttpRequest(String url,  
36 - MultiValueMap<String, String> headers,  
37 - MultiValueMap<String, String> body) {  
38 - // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢?  
39 - // 3. 发起请求  
40 - HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);  
41 - ResponseEntity<String> responseEntity;  
42 - try {  
43 - responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);  
44 - log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);  
45 - } catch (RestClientException e) {  
46 - log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());  
47 - throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR);  
48 - }  
49 - return responseEntity;  
50 - }  
51 -  
52 - protected MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,  
53 - List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {  
54 - Map<String, Object> processVariables = processInstance.getProcessVariables();  
55 - MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();  
56 - headers.add(HEADER_TENANT_ID, processInstance.getTenantId());  
57 - SimpleModelUtils.addHttpRequestParam(headers, headerSettings, processVariables);  
58 - return headers;  
59 - }  
60 -  
61 - protected MultiValueMap<String, String> buildHttpBody(ProcessInstance processInstance,  
62 - List<BpmSimpleModelNodeVO.HttpRequestParam> bodySettings) {  
63 - Map<String, Object> processVariables = processInstance.getProcessVariables();  
64 - MultiValueMap<String, String> body = new LinkedMultiValueMap<>();  
65 - SimpleModelUtils.addHttpRequestParam(body, bodySettings, processVariables);  
66 - body.add("processInstanceId", processInstance.getId());  
67 - return body;  
68 - }  
69 -  
70 } 14 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java
@@ -2,13 +2,15 @@ package cn.iocoder.yudao.module.bpm.service.task.trigger.http; @@ -2,13 +2,15 @@ package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2 2
3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; 4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
5 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; 6 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
6 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 8 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
7 import jakarta.annotation.Resource; 9 import jakarta.annotation.Resource;
8 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
9 import org.flowable.engine.runtime.ProcessInstance; 11 import org.flowable.engine.runtime.ProcessInstance;
10 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
11 -import org.springframework.util.MultiValueMap; 13 +import org.springframework.web.client.RestTemplate;
12 14
13 /** 15 /**
14 * BPM HTTP 回调触发器 16 * BPM HTTP 回调触发器
@@ -20,6 +22,9 @@ import org.springframework.util.MultiValueMap; @@ -20,6 +22,9 @@ import org.springframework.util.MultiValueMap;
20 public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger { 22 public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger {
21 23
22 @Resource 24 @Resource
  25 + private RestTemplate restTemplate;
  26 +
  27 + @Resource
23 private BpmProcessInstanceService processInstanceService; 28 private BpmProcessInstanceService processInstanceService;
24 29
25 @Override 30 @Override
@@ -36,16 +41,19 @@ public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger { @@ -36,16 +41,19 @@ public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger {
36 log.error("[execute][流程({}) HTTP 回调触发器配置为空]", processInstanceId); 41 log.error("[execute][流程({}) HTTP 回调触发器配置为空]", processInstanceId);
37 return; 42 return;
38 } 43 }
39 -  
40 - // 2.1 设置请求头 44 + // 2. 发起请求
41 ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); 45 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 // 重要:回调请求 taskDefineKey 需要传给被调用方,用于回调执行 46 // 重要:回调请求 taskDefineKey 需要传给被调用方,用于回调执行
46 - body.add("taskDefineKey", setting.getCallbackTaskDefineKey());  
47 -  
48 - // 3. 发起请求  
49 - sendHttpRequest(setting.getUrl(), headers, body); 47 + setting.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam()
  48 + .setKey("taskDefineKey")
  49 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
  50 + .setValue(setting.getCallbackTaskDefineKey()));
  51 + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
  52 + setting.getUrl(),
  53 + setting.getHeader(),
  54 + setting.getBody(),
  55 + false, null,
  56 + restTemplate,
  57 + processInstanceService);
50 } 58 }
51 } 59 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java
1 package cn.iocoder.yudao.module.bpm.service.task.trigger.http; 1 package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.hutool.core.util.StrUtil;  
5 -import cn.iocoder.yudao.framework.common.core.KeyValue;  
6 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 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; 4 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; 5 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
10 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 7 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
11 -import com.fasterxml.jackson.core.type.TypeReference;  
12 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
13 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
14 import org.flowable.engine.runtime.ProcessInstance; 10 import org.flowable.engine.runtime.ProcessInstance;
15 -import org.springframework.http.ResponseEntity;  
16 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
17 -import org.springframework.util.MultiValueMap;  
18 -  
19 -import java.util.HashMap;  
20 -import java.util.List;  
21 -import java.util.Map; 12 +import org.springframework.web.client.RestTemplate;
22 13
23 /** 14 /**
24 * BPM 发送同步 HTTP 请求触发器 15 * BPM 发送同步 HTTP 请求触发器
@@ -30,6 +21,9 @@ import java.util.Map; @@ -30,6 +21,9 @@ import java.util.Map;
30 public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { 21 public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
31 22
32 @Resource 23 @Resource
  24 + private RestTemplate restTemplate;
  25 +
  26 + @Resource
33 private BpmProcessInstanceService processInstanceService; 27 private BpmProcessInstanceService processInstanceService;
34 28
35 @Override 29 @Override
@@ -45,56 +39,15 @@ public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { @@ -45,56 +39,15 @@ public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
45 log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId); 39 log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId);
46 return; 40 return;
47 } 41 }
48 -  
49 - // 2.1 设置请求头 42 + // 2. 发起请求
50 ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); 43 ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
51 - MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader());  
52 - // 2.2 设置请求体  
53 - MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody());  
54 -  
55 - // 3. 发起请求  
56 - ResponseEntity<String> responseEntity = sendHttpRequest(setting.getUrl(), headers, body);  
57 -  
58 - // 4.1 判断是否需要解析返回值  
59 - if (responseEntity == null || StrUtil.isEmpty(responseEntity.getBody())  
60 - || !responseEntity.getStatusCode().is2xxSuccessful()  
61 - || CollUtil.isEmpty(setting.getResponse())) {  
62 - return;  
63 - }  
64 - // 4.2 解析返回值, 返回值必须符合 CommonResult 规范。  
65 - CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly(  
66 - responseEntity.getBody(), new TypeReference<>() {  
67 - });  
68 - if (respResult == null || !respResult.isSuccess()) {  
69 - return;  
70 - }  
71 - // 4.3 获取需要更新的流程变量  
72 - Map<String, Object> updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), setting.getResponse());  
73 - // 4.4 更新流程变量  
74 - if (CollUtil.isNotEmpty(updateVariables)) {  
75 - processInstanceService.updateProcessInstanceVariables(processInstanceId, updateVariables);  
76 - }  
77 - }  
78 -  
79 - /**  
80 - * 从请求返回值获取需要更新的流程变量  
81 - *  
82 - * @param result 请求返回结果  
83 - * @param responseSettings 返回设置  
84 - * @return 需要更新的流程变量  
85 - */  
86 - private Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String, Object> result,  
87 - List<KeyValue<String, String>> responseSettings) {  
88 - Map<String, Object> updateVariables = new HashMap<>();  
89 - if (CollUtil.isEmpty(result)) {  
90 - return updateVariables;  
91 - }  
92 - responseSettings.forEach(responseSetting -> {  
93 - if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) {  
94 - updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue()));  
95 - }  
96 - });  
97 - return updateVariables; 44 + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
  45 + setting.getUrl(),
  46 + setting.getHeader(),
  47 + setting.getBody(),
  48 + true, setting.getResponse(),
  49 + restTemplate,
  50 + processInstanceService);
98 } 51 }
99 52
100 } 53 }