原理:
- 在流程表单数据正式提交审核前,将流程表单数据 formData 及流程执行实例 ExecutionEntity 传递给接口
- 接口在流程定义取得当前节点信息并循环查找出线 SequenceFlow 还需要注意遇到网关时应该怎样处理
- 使用变量执行出线 SequenceFlow 条件(类似完成提交任务操作)
- 找出第一个用户任务UserTask 根据这个UserTask中信息,我们就能拿到流程审核人了
- 最重要的一点,在第三点中使用变量去执行条件的时候,变量会被持久化至数据库中,所以我们一定要在事务中进行操作,操作完成后回滚清空当前事务,避免数据紊乱
项目完整源码链接
以下是全部代码,此逻辑仅供参考
package com.nutzfw.core.plugin.flowable.cmd;
import org.apache.commons.collections.CollectionUtils;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.condition.ConditionUtil;
import java.util.List;
import java.util.Map;
/**
* @author huchuc@vip.qq.com
* @date: 2019/7/9
* 使用示例,一定要放到事务中,否则变量会入库,导致数据紊乱
* try {
* Trans.begin();
* UserTask userTask = managementService.executeCommand(new FindNextUserTaskNodeCmd(execution, bpmnModel, vars));
* System.out.println(userTask.getId());
* } finally {
* Trans.clear(true);
* }
*/
public class FindNextUserTaskNodeCmd implements Command<UserTask> {
private final ExecutionEntity execution;
private final BpmnModel bpmnModel;
private Map<String, Object> vars;
/**
* 返回下一用户节点
*/
private UserTask nextUserTask;
/**
* @param execution 当前执行实例
* @param bpmnModel 当前执行实例的模型
* @param vars 参与计算流程条件的变量
*/
public FindNextUserTaskNodeCmd(ExecutionEntity execution, BpmnModel bpmnModel, Map<String, Object> vars) {
this.execution = execution;
this.bpmnModel = bpmnModel;
this.vars = vars;
}
/**
* @param execution 当前执行实例
* @param bpmnModel 当前执行实例的模型
*/
public FindNextUserTaskNodeCmd(ExecutionEntity execution, BpmnModel bpmnModel) {
this.execution = execution;
this.bpmnModel = bpmnModel;
}
@Override
public UserTask execute(CommandContext commandContext) {
execution.setVariables(vars);
FlowElement currentNode = bpmnModel.getFlowElement(execution.getActivityId());
List<SequenceFlow> outgoingFlows = ((FlowNode) currentNode).getOutgoingFlows();
if (CollectionUtils.isNotEmpty(outgoingFlows)) {
this.findNextUserTaskNode(outgoingFlows, execution);
}
return nextUserTask;
}
void findNextUserTaskNode(List<SequenceFlow> outgoingFlows, ExecutionEntity execution) {
sw:
for (SequenceFlow outgoingFlow : outgoingFlows) {
if (ConditionUtil.hasTrueCondition(outgoingFlow, execution)) {
if (outgoingFlow.getTargetFlowElement() instanceof ExclusiveGateway) {
//只有排他网关才继续
ExclusiveGateway exclusiveGateway = (ExclusiveGateway) outgoingFlow.getTargetFlowElement();
findNextUserTaskNode(exclusiveGateway.getOutgoingFlows(), execution);
} else if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {
nextUserTask = (UserTask) outgoingFlow.getTargetFlowElement();
//找到第一个符合条件的userTask就跳出循环
break sw;
}
}
}
}
}