!1283 feat: 流程前后置通知
Merge pull request !1283 from Lesan/feature/bpm-流程前后置通知
This commit is contained in:
commit
6f2e538927
|
@ -1,6 +1,8 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmAutoApproveTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
|
||||
|
@ -80,6 +82,12 @@ public class BpmModelMetaInfoVO {
|
|||
@Schema(description = "摘要设置", example = "{}")
|
||||
private SummarySetting summarySetting;
|
||||
|
||||
@Schema(description = "流程前置通知设置", example = "{}")
|
||||
private HttpRequestSetting PreProcessNotifySetting;
|
||||
|
||||
@Schema(description = "流程后置通知设置", example = "{}")
|
||||
private HttpRequestSetting PostProcessNotifySetting;
|
||||
|
||||
@Schema(description = "流程 ID 规则")
|
||||
@Data
|
||||
@Valid
|
||||
|
@ -132,4 +140,32 @@ public class BpmModelMetaInfoVO {
|
|||
|
||||
}
|
||||
|
||||
@Schema(description = "http 请求通知设置", example = "{}")
|
||||
@Data
|
||||
public static class HttpRequestSetting {
|
||||
|
||||
@Schema(description = "请求路径", example = "http://127.0.0.1")
|
||||
@NotEmpty(message = "请求 URL 不能为空")
|
||||
@URL(message = "请求 URL 格式不正确")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "请求头参数设置", example = "[]")
|
||||
@Valid
|
||||
private List<BpmSimpleModelNodeVO.HttpRequestParam> header;
|
||||
|
||||
@Schema(description = "请求头参数设置", example = "[]")
|
||||
@Valid
|
||||
private List<BpmSimpleModelNodeVO.HttpRequestParam> body;
|
||||
|
||||
/**
|
||||
* 请求返回处理设置,用于修改流程表单值
|
||||
* <p>
|
||||
* key:表示要修改的流程表单字段名(name)
|
||||
* value:接口返回的字段名
|
||||
*/
|
||||
@Schema(description = "请求返回处理设置", example = "[]")
|
||||
private List<KeyValue<String, String>> response;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -189,4 +189,16 @@ public class BpmProcessDefinitionInfoDO extends BaseDO {
|
|||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private BpmModelMetaInfoVO.SummarySetting summarySetting;
|
||||
|
||||
/**
|
||||
* 流程前置通知设置
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private BpmModelMetaInfoVO.HttpRequestSetting PreProcessNotifySetting;
|
||||
|
||||
/**
|
||||
* 流程后置通知设置
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private BpmModelMetaInfoVO.HttpRequestSetting PostProcessNotifySetting;
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||
public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
|
||||
|
||||
public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
|
||||
.add(FlowableEngineEventType.PROCESS_CREATED)
|
||||
.add(FlowableEngineEventType.PROCESS_COMPLETED)
|
||||
.add(FlowableEngineEventType.PROCESS_CANCELLED)
|
||||
.build();
|
||||
|
@ -34,6 +35,11 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
|
|||
super(PROCESS_INSTANCE_EVENTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCreated(FlowableEngineEntityEvent event) {
|
||||
processInstanceService.processProcessInstanceCreated((ProcessInstance)event.getEntity());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCompleted(FlowableEngineEntityEvent event) {
|
||||
processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity());
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR;
|
||||
|
||||
/**
|
||||
* 工作流发起 HTTP 请求工具类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
public class BpmHttpRequestUtils {
|
||||
|
||||
public static void executeBpmHttpRequest(ProcessInstance processInstance,
|
||||
String url,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> headerParam,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> bodyParam,
|
||||
Boolean handleResponse,
|
||||
List<KeyValue<String, String>> response,
|
||||
RestTemplate restTemplate,
|
||||
BpmProcessInstanceService processInstanceService) {
|
||||
|
||||
// 1.1 设置请求头
|
||||
MultiValueMap<String, String> headers = BpmHttpRequestUtils.buildHttpHeaders(processInstance, headerParam);
|
||||
// 1.2 设置请求体
|
||||
MultiValueMap<String, String> body = BpmHttpRequestUtils.buildHttpBody(processInstance, bodyParam);
|
||||
|
||||
// 2. 发起请求
|
||||
ResponseEntity<String> responseEntity = BpmHttpRequestUtils.sendHttpRequest(url, headers, body, restTemplate);
|
||||
|
||||
// 3. 处理返回
|
||||
if (Boolean.TRUE.equals(handleResponse)) {
|
||||
// 3.1 判断是否需要解析返回值
|
||||
if (responseEntity == null || StrUtil.isEmpty(responseEntity.getBody())
|
||||
|| !responseEntity.getStatusCode().is2xxSuccessful()
|
||||
|| CollUtil.isEmpty(response)) {
|
||||
return;
|
||||
}
|
||||
// 3.2 解析返回值, 返回值必须符合 CommonResult 规范。
|
||||
CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly(
|
||||
responseEntity.getBody(), new TypeReference<>() {
|
||||
});
|
||||
if (respResult == null || !respResult.isSuccess()) {
|
||||
return;
|
||||
}
|
||||
// 3.3 获取需要更新的流程变量
|
||||
Map<String, Object> updateVariables = BpmHttpRequestUtils.getNeedUpdatedVariablesFromResponse(respResult.getData(), response);
|
||||
// 3.4 更新流程变量
|
||||
if (CollUtil.isNotEmpty(updateVariables)) {
|
||||
processInstanceService.updateProcessInstanceVariables(processInstance.getId(), updateVariables);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ResponseEntity<String> sendHttpRequest(String url,
|
||||
MultiValueMap<String, String> headers,
|
||||
MultiValueMap<String, String> body,
|
||||
RestTemplate restTemplate) {
|
||||
// 3. 发起请求
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
|
||||
ResponseEntity<String> responseEntity;
|
||||
try {
|
||||
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
|
||||
log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
|
||||
} catch (RestClientException e) {
|
||||
log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
|
||||
throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR);
|
||||
}
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
headers.add(HEADER_TENANT_ID, processInstance.getTenantId());
|
||||
addHttpRequestParam(headers, headerSettings, processVariables);
|
||||
return headers;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> buildHttpBody(ProcessInstance processInstance,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> bodySettings) {
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
|
||||
addHttpRequestParam(body, bodySettings, processVariables);
|
||||
body.add("processInstanceId", processInstance.getId());
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求返回值获取需要更新的流程变量
|
||||
*
|
||||
* @param result 请求返回结果
|
||||
* @param responseSettings 返回设置
|
||||
* @return 需要更新的流程变量
|
||||
*/
|
||||
public static Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String, Object> result,
|
||||
List<KeyValue<String, String>> responseSettings) {
|
||||
Map<String, Object> updateVariables = new HashMap<>();
|
||||
if (CollUtil.isEmpty(result)) {
|
||||
return updateVariables;
|
||||
}
|
||||
responseSettings.forEach(responseSetting -> {
|
||||
if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) {
|
||||
updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue()));
|
||||
}
|
||||
});
|
||||
return updateVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 HTTP 请求参数。请求头或者请求体
|
||||
*
|
||||
* @param params HTTP 请求参数
|
||||
* @param paramSettings HTTP 请求参数设置
|
||||
* @param processVariables 流程变量
|
||||
*/
|
||||
public static void addHttpRequestParam(MultiValueMap<String, String> params,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> paramSettings,
|
||||
Map<String, Object> processVariables) {
|
||||
if (CollUtil.isEmpty(paramSettings)) {
|
||||
return;
|
||||
}
|
||||
paramSettings.forEach(item -> {
|
||||
if (item.getType().equals(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())) {
|
||||
params.add(item.getKey(), item.getValue());
|
||||
} else if (item.getType().equals(BpmHttpRequestParamTypeEnum.FROM_FORM.getType())) {
|
||||
params.add(item.getKey(), processVariables.get(item.getValue()).toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,6 @@ import org.flowable.bpmn.model.Process;
|
|||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -1002,27 +1001,4 @@ public class SimpleModelUtils {
|
|||
return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
|
||||
}
|
||||
|
||||
// TODO @芋艿:【高】要不要优化下,抽个 HttpUtils
|
||||
|
||||
/**
|
||||
* 添加 HTTP 请求参数。请求头或者请求体
|
||||
*
|
||||
* @param params HTTP 请求参数
|
||||
* @param paramSettings HTTP 请求参数设置
|
||||
* @param processVariables 流程变量
|
||||
*/
|
||||
public static void addHttpRequestParam(MultiValueMap<String, String> params,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> paramSettings,
|
||||
Map<String, Object> processVariables) {
|
||||
if (CollUtil.isEmpty(paramSettings)) {
|
||||
return;
|
||||
}
|
||||
paramSettings.forEach(item -> {
|
||||
if (item.getType().equals(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())) {
|
||||
params.add(item.getKey(), item.getValue());
|
||||
} else if (item.getType().equals(BpmHttpRequestParamTypeEnum.FROM_FORM.getType())) {
|
||||
params.add(item.getKey(), processVariables.get(item.getValue()).toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,4 +182,10 @@ public interface BpmProcessInstanceService {
|
|||
*/
|
||||
void processProcessInstanceCompleted(ProcessInstance instance);
|
||||
|
||||
/**
|
||||
* 处理 ProcessInstance 开始事件,例如说:流程前置通知
|
||||
*
|
||||
* @param instance 流程任务
|
||||
*/
|
||||
void processProcessInstanceCreated(ProcessInstance instance);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidat
|
|||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
|
||||
|
@ -62,6 +63,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -120,6 +122,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
@Resource
|
||||
private BpmProcessIdRedisDAO processIdRedisDAO;
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
// ========== Query 查询相关方法 ==========
|
||||
|
||||
@Override
|
||||
|
@ -902,6 +907,46 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
// 3. 发送流程实例的状态事件
|
||||
processInstanceEventPublisher.sendProcessInstanceResultEvent(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
|
||||
|
||||
// 4. 流程后置通知
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
|
||||
getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
if (ObjUtil.isNotNull(processDefinitionInfo) &&
|
||||
ObjUtil.isNotNull(processDefinitionInfo.getPostProcessNotifySetting())) {
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getPostProcessNotifySetting();
|
||||
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(),
|
||||
setting.getHeader(),
|
||||
setting.getBody(),
|
||||
true, setting.getResponse(),
|
||||
restTemplate,
|
||||
this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processProcessInstanceCreated(ProcessInstance instance) {
|
||||
// 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
|
||||
FlowableUtils.execute(instance.getTenantId(), () -> {
|
||||
// 流程前置通知
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
|
||||
getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
if (ObjUtil.isNotNull(processDefinitionInfo) &&
|
||||
ObjUtil.isNotNull(processDefinitionInfo.getPreProcessNotifySetting())) {
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getPreProcessNotifySetting();
|
||||
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(),
|
||||
setting.getHeader(),
|
||||
setting.getBody(),
|
||||
true, setting.getResponse(),
|
||||
restTemplate,
|
||||
this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,20 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.task.listener;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.impl.el.FixedValue;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseListenerConfig;
|
||||
|
||||
/**
|
||||
|
@ -50,46 +41,35 @@ public class BpmUserTaskListener implements TaskListener {
|
|||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
// 1. 获取所需基础信息
|
||||
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(delegateTask.getProcessInstanceId());
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(delegateTask.getProcessInstanceId());
|
||||
BpmSimpleModelNodeVO.ListenerHandler listenerHandler = parseListenerConfig(listenerConfig);
|
||||
|
||||
// 2. 获取请求头和请求体
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
|
||||
SimpleModelUtils.addHttpRequestParam(headers, listenerHandler.getHeader(), processVariables);
|
||||
SimpleModelUtils.addHttpRequestParam(body, listenerHandler.getBody(), processVariables);
|
||||
// 2.1 请求头默认参数
|
||||
if (StrUtil.isNotEmpty(delegateTask.getTenantId())) {
|
||||
headers.add(HEADER_TENANT_ID, delegateTask.getTenantId());
|
||||
}
|
||||
// 2.2 请求体默认参数
|
||||
// 2. 发起请求
|
||||
// TODO @芋艿:哪些默认参数,后续再调研下;感觉可以搞个 task 字段,把整个 delegateTask 放进去;
|
||||
body.add("processInstanceId", delegateTask.getProcessInstanceId());
|
||||
body.add("assignee", delegateTask.getAssignee());
|
||||
body.add("taskDefinitionKey", delegateTask.getTaskDefinitionKey());
|
||||
body.add("taskId", delegateTask.getId());
|
||||
listenerHandler.getBody()
|
||||
.add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("processInstanceId")
|
||||
.setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
|
||||
.setValue(delegateTask.getProcessInstanceId()));
|
||||
listenerHandler.getBody()
|
||||
.add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("assignee")
|
||||
.setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
|
||||
.setValue(delegateTask.getAssignee()));
|
||||
listenerHandler.getBody()
|
||||
.add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskDefinitionKey")
|
||||
.setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
|
||||
.setValue(delegateTask.getTaskDefinitionKey()));
|
||||
listenerHandler.getBody()
|
||||
.add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskId")
|
||||
.setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
|
||||
.setValue(delegateTask.getId()));
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
|
||||
listenerHandler.getPath(),
|
||||
listenerHandler.getHeader(),
|
||||
listenerHandler.getBody(),
|
||||
false, null,
|
||||
restTemplate,
|
||||
processInstanceService);
|
||||
|
||||
// 3. 异步发起请求
|
||||
// TODO @芋艿:确认要同步,还是异步
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
|
||||
try {
|
||||
ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST,
|
||||
requestEntity, String.class);
|
||||
log.info("[notify][监听器:{},事件类型:{},请求头:{},请求体:{},响应结果:{}]",
|
||||
DELEGATE_EXPRESSION,
|
||||
delegateTask.getEventName(),
|
||||
headers,
|
||||
body,
|
||||
responseEntity);
|
||||
} catch (RestClientException e) {
|
||||
log.error("[error][监听器:{},事件类型:{},请求头:{},请求体:{},请求出错:{}]",
|
||||
DELEGATE_EXPRESSION,
|
||||
delegateTask.getEventName(),
|
||||
headers,
|
||||
body,
|
||||
e.getMessage());
|
||||
}
|
||||
// 4. 是否需要后续操作?TODO 芋艿:待定!
|
||||
// 3. 是否需要后续操作?TODO 芋艿:待定!
|
||||
}
|
||||
}
|
|
@ -1,25 +1,7 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR;
|
||||
|
||||
/**
|
||||
* BPM 发送 HTTP 请求触发器抽象类
|
||||
|
@ -29,42 +11,4 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTA
|
|||
@Slf4j
|
||||
public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger {
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
protected ResponseEntity<String> sendHttpRequest(String url,
|
||||
MultiValueMap<String, String> headers,
|
||||
MultiValueMap<String, String> body) {
|
||||
// TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢?
|
||||
// 3. 发起请求
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
|
||||
ResponseEntity<String> responseEntity;
|
||||
try {
|
||||
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
|
||||
log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
|
||||
} catch (RestClientException e) {
|
||||
log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
|
||||
throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR);
|
||||
}
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
protected MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
headers.add(HEADER_TENANT_ID, processInstance.getTenantId());
|
||||
SimpleModelUtils.addHttpRequestParam(headers, headerSettings, processVariables);
|
||||
return headers;
|
||||
}
|
||||
|
||||
protected MultiValueMap<String, String> buildHttpBody(ProcessInstance processInstance,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> bodySettings) {
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
|
||||
SimpleModelUtils.addHttpRequestParam(body, bodySettings, processVariables);
|
||||
body.add("processInstanceId", processInstance.getId());
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,13 +2,15 @@ package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* BPM HTTP 回调触发器
|
||||
|
@ -19,6 +21,9 @@ import org.springframework.util.MultiValueMap;
|
|||
@Slf4j
|
||||
public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger {
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
|
@ -36,16 +41,19 @@ public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger {
|
|||
log.error("[execute][流程({}) HTTP 回调触发器配置为空]", processInstanceId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2.1 设置请求头
|
||||
// 2. 发起请求
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
|
||||
MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader());
|
||||
// 2.2 设置请求体
|
||||
MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody());
|
||||
// 重要:回调请求 taskDefineKey 需要传给被调用方,用于回调执行
|
||||
body.add("taskDefineKey", setting.getCallbackTaskDefineKey());
|
||||
|
||||
// 3. 发起请求
|
||||
sendHttpRequest(setting.getUrl(), headers, body);
|
||||
setting.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam()
|
||||
.setKey("taskDefineKey")
|
||||
.setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())
|
||||
.setValue(setting.getCallbackTaskDefineKey()));
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
|
||||
setting.getUrl(),
|
||||
setting.getHeader(),
|
||||
setting.getBody(),
|
||||
false, null,
|
||||
restTemplate,
|
||||
processInstanceService);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,15 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* BPM 发送同步 HTTP 请求触发器
|
||||
|
@ -29,6 +20,9 @@ import java.util.Map;
|
|||
@Slf4j
|
||||
public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
|
@ -45,56 +39,15 @@ public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
|
|||
log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2.1 设置请求头
|
||||
// 2. 发起请求
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
|
||||
MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader());
|
||||
// 2.2 设置请求体
|
||||
MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody());
|
||||
|
||||
// 3. 发起请求
|
||||
ResponseEntity<String> responseEntity = sendHttpRequest(setting.getUrl(), headers, body);
|
||||
|
||||
// 4.1 判断是否需要解析返回值
|
||||
if (responseEntity == null || StrUtil.isEmpty(responseEntity.getBody())
|
||||
|| !responseEntity.getStatusCode().is2xxSuccessful()
|
||||
|| CollUtil.isEmpty(setting.getResponse())) {
|
||||
return;
|
||||
}
|
||||
// 4.2 解析返回值, 返回值必须符合 CommonResult 规范。
|
||||
CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly(
|
||||
responseEntity.getBody(), new TypeReference<>() {
|
||||
});
|
||||
if (respResult == null || !respResult.isSuccess()) {
|
||||
return;
|
||||
}
|
||||
// 4.3 获取需要更新的流程变量
|
||||
Map<String, Object> updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), setting.getResponse());
|
||||
// 4.4 更新流程变量
|
||||
if (CollUtil.isNotEmpty(updateVariables)) {
|
||||
processInstanceService.updateProcessInstanceVariables(processInstanceId, updateVariables);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求返回值获取需要更新的流程变量
|
||||
*
|
||||
* @param result 请求返回结果
|
||||
* @param responseSettings 返回设置
|
||||
* @return 需要更新的流程变量
|
||||
*/
|
||||
private Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String, Object> result,
|
||||
List<KeyValue<String, String>> responseSettings) {
|
||||
Map<String, Object> updateVariables = new HashMap<>();
|
||||
if (CollUtil.isEmpty(result)) {
|
||||
return updateVariables;
|
||||
}
|
||||
responseSettings.forEach(responseSetting -> {
|
||||
if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) {
|
||||
updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue()));
|
||||
}
|
||||
});
|
||||
return updateVariables;
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
|
||||
setting.getUrl(),
|
||||
setting.getHeader(),
|
||||
setting.getBody(),
|
||||
true, setting.getResponse(),
|
||||
restTemplate,
|
||||
processInstanceService);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue