Flowable工作流 实现多实例任务(会签或签)

版本:Flowable 6.7.0

配置完成条件

会签:${nrOfCompletedInstances==nrOfInstances}

或签:${nrOfCompletedInstances>=1} 

固定集合、变量参数为approverList、approver

自定义多实例并行行为解析类

package com.twqc.modules.lowcode.bpm.framework.flowable.core.behavior;

import com.twqc.common.system.api.ISysBaseAPI;
import com.twqc.common.util.CollectionUtils;
import com.twqc.modules.lowcode.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import com.twqc.modules.lowcode.bpm.service.definition.BpmTaskAssignRuleService;
import com.twqc.modules.lowcode.bpm.service.definition.BpmUserGroupService;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Activity;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;

import java.util.*;

/**
 * 多实例并行行为解析类
 *
 * @author wsl
 * @date 2023/5/4
 */
@Slf4j
public class MultiInstanceParallelBehavior extends ParallelMultiInstanceBehavior {

    @Setter
    private BpmTaskAssignRuleService bpmTaskRuleService;
    @Setter
    private BpmUserGroupService userGroupService;
    @Setter
    private ISysBaseAPI iSysBaseAPI;
    @Setter
    private BpmTaskAssignUsersResolve bpmTaskAssignUsersResolve;

    /**
     * 任务分配脚本
     */
    private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();

    public void setScripts(List<BpmTaskAssignScript> scripts) {
        this.scriptMap = CollectionUtils.convertMap(scripts, script -> script.getEnum().getId());
    }

    public MultiInstanceParallelBehavior(Activity activity, AbstractBpmnActivityBehavior originalActivityBehavior) {
        super(activity, originalActivityBehavior);
    }

    @Override
    protected int createInstances(DelegateExecution multiInstanceRootExecution) {
        log.info("MultiInstanceParallelBehavior.createInstances start");
        // 获取当前节点的候选执行人
        List<String> userList = new ArrayList<>();
        HandleAssignmentsCommon handleAssignmentsCommon = new HandleAssignmentsCommon();
        handleAssignmentsCommon.setBpmTaskRuleService(bpmTaskRuleService);
        handleAssignmentsCommon.setUserGroupService(userGroupService);
        handleAssignmentsCommon.setISysBaseAPI(iSysBaseAPI);
        handleAssignmentsCommon.setScripts(scriptMap);
        handleAssignmentsCommon.setBpmTaskAssignUsersResolve(bpmTaskAssignUsersResolve);
        Set<String> candidateUsers = handleAssignmentsCommon.calculateTaskCandidateUsers(multiInstanceRootExecution.getProcessDefinitionId(), multiInstanceRootExecution.getCurrentActivityId(), multiInstanceRootExecution.getId(), multiInstanceRootExecution.getProcessInstanceId());
        candidateUsers.forEach(user -> {
            userList.add(user);
        });
        // 设置候选执行人
        multiInstanceRootExecution.setVariable("approverList", userList);
        setLoopVariable(multiInstanceRootExecution, NUMBER_OF_INSTANCES, userList.size());
        setLoopVariable(multiInstanceRootExecution, NUMBER_OF_ACTIVE_INSTANCES, userList.size());
        return super.createInstances(multiInstanceRootExecution);
    }

}

自定义多实例串行行为解析类

package com.twqc.modules.lowcode.bpm.framework.flowable.core.behavior;

import com.twqc.common.system.api.ISysBaseAPI;
import com.twqc.common.util.CollectionUtils;
import com.twqc.modules.lowcode.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import com.twqc.modules.lowcode.bpm.service.definition.BpmTaskAssignRuleService;
import com.twqc.modules.lowcode.bpm.service.definition.BpmUserGroupService;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Activity;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;

import java.util.*;

/**
 * 多实例串行行为解析类
 *
 * @author wsl
 * @date 2023/5/4
 */
@Slf4j
public class MultiInstanceSequentialBehavior extends SequentialMultiInstanceBehavior {

    @Setter
    private BpmTaskAssignRuleService bpmTaskRuleService;
    @Setter
    private BpmUserGroupService userGroupService;
    @Setter
    private ISysBaseAPI iSysBaseAPI;
    @Setter
    private BpmTaskAssignUsersResolve bpmTaskAssignUsersResolve;

    /**
     * 任务分配脚本
     */
    private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();

    public void setScripts(List<BpmTaskAssignScript> scripts) {
        this.scriptMap = CollectionUtils.convertMap(scripts, script -> script.getEnum().getId());
    }

    public MultiInstanceSequentialBehavior(Activity activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
        super(activity, innerActivityBehavior);
    }

    @Override
    protected int createInstances(DelegateExecution multiInstanceRootExecution) {
        log.info("MultiInstanceSequentialBehavior.createInstances start");
        // 获取当前节点的候选执行人,此处自行替换为获取候选用户逻辑
        List<String> userList = new ArrayList<>();
        HandleAssignmentsCommon handleAssignmentsCommon = new HandleAssignmentsCommon();
        handleAssignmentsCommon.setBpmTaskRuleService(bpmTaskRuleService);
        handleAssignmentsCommon.setUserGroupService(userGroupService);
        handleAssignmentsCommon.setISysBaseAPI(iSysBaseAPI);
        handleAssignmentsCommon.setBpmTaskAssignUsersResolve(bpmTaskAssignUsersResolve);
        handleAssignmentsCommon.setScripts(scriptMap);
        Set<String> candidateUsers = handleAssignmentsCommon.calculateTaskCandidateUsers(multiInstanceRootExecution.getProcessDefinitionId(), multiInstanceRootExecution.getCurrentActivityId(), multiInstanceRootExecution.getId(), multiInstanceRootExecution.getProcessInstanceId());
        candidateUsers.forEach(user -> {
            userList.add(user);
        });
        // 设置候选执行人
        multiInstanceRootExecution.setVariable("approverList", userList);
        setLoopVariable(multiInstanceRootExecution, NUMBER_OF_INSTANCES, userList.size());
        setLoopVariable(multiInstanceRootExecution, NUMBER_OF_ACTIVE_INSTANCES, userList.size());
        return super.createInstances(multiInstanceRootExecution);
    }

}

 工厂实现类

package com.twqc.modules.lowcode.bpm.framework.flowable.core.behavior;

import com.twqc.common.system.api.ISysBaseAPI;
import com.twqc.modules.lowcode.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import com.twqc.modules.lowcode.bpm.service.definition.BpmTaskAssignRuleService;
import com.twqc.modules.lowcode.bpm.service.definition.BpmUserGroupService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString;
import org.flowable.bpmn.model.Activity;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;

import java.util.List;

/**
 * 自定义的 ActivityBehaviorFactory 实现类,目的如下:
 * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
 *
 * @author YT
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {

    @Setter
    private BpmTaskAssignRuleService bpmTaskRuleService;

    @Setter
    private BpmUserGroupService userGroupService;

    @Setter
    private ISysBaseAPI iSysBaseAPI;

    @Setter
    private List<BpmTaskAssignScript> scripts;

    @Setter
    private BpmTaskAssignUsersResolve bpmTaskAssignUsersResolve;

    private ExpressionManager expressionManager;

    /**
     * 重写父类的方法,自定义串行多实例行为,用于控制顺序(串行)多实例任务的执行逻辑。
     *
     * @param activity
     * @param innerActivityBehavior
     * @return
     */
    @Override
    public SequentialMultiInstanceBehavior createSequentialMultiInstanceBehavior(Activity activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
        MultiInstanceSequentialBehavior multiInstanceSequentialBehavior = new MultiInstanceSequentialBehavior(activity, innerActivityBehavior);
        multiInstanceSequentialBehavior.setBpmTaskRuleService(bpmTaskRuleService);
        multiInstanceSequentialBehavior.setISysBaseAPI(iSysBaseAPI);
        multiInstanceSequentialBehavior.setUserGroupService(userGroupService);
        multiInstanceSequentialBehavior.setScripts(scripts);
        multiInstanceSequentialBehavior.setBpmTaskAssignUsersResolve(bpmTaskAssignUsersResolve);
        return multiInstanceSequentialBehavior;
    }

    /**
     * 重写父类的方法,自定义并行多实例行为,用于控制并行多实例任务的执行逻辑。
     *
     * @param activity
     * @param innerActivityBehavior
     * @return
     */
    @Override
    public ParallelMultiInstanceBehavior createParallelMultiInstanceBehavior(Activity activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
        MultiInstanceParallelBehavior multiInstanceParallelBehavior = new MultiInstanceParallelBehavior(activity, innerActivityBehavior);
        multiInstanceParallelBehavior.setBpmTaskRuleService(bpmTaskRuleService);
        multiInstanceParallelBehavior.setISysBaseAPI(iSysBaseAPI);
        multiInstanceParallelBehavior.setUserGroupService(userGroupService);
        multiInstanceParallelBehavior.setScripts(scripts);
        multiInstanceParallelBehavior.setBpmTaskAssignUsersResolve(bpmTaskAssignUsersResolve);
        return multiInstanceParallelBehavior;
    }
}

多实例任务监听器

package com.twqc.modules.lowcode.bpm.framework.flowable.core.listener;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.engine.ProcessEngines;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;

/**
 * 多任务监听,用于设置审批人
 * 配置在多人任务节点的任务监听器中
 *
 * @author wangsl
 */
@Component
@Slf4j
public class BpmMultiInstanceTaskListener implements FlowableEventListener {

    @Override
    public void onEvent(FlowableEvent event) {
        // 判断是否为任务创建事件
        if (FlowableEngineEventType.TASK_CREATED.equals(event.getType())) {
            if (event instanceof FlowableEntityEventImpl) {
                FlowableEntityEventImpl entityEvent = (FlowableEntityEventImpl) event;
                Object entity = entityEvent.getEntity();
                if (entity instanceof TaskEntity) {
                    TaskEntity taskEntity = (TaskEntity) entity;
                    // 判断是否为多实例任务
                    boolean isMultiInstance = isMultiInstance(taskEntity);
                    if (isMultiInstance) {
                        log.info("task is multiInstance, taskId:{}", taskEntity.getId());
                        String taskId = taskEntity.getId();
                        TaskService taskService = ProcessEngines.getDefaultProcessEngine().getTaskService();
                        Object user = taskService.getVariable(taskId, "approver");
                        // 设置审批人
                        if (ObjectUtil.isNotEmpty(user)) {
                            String userId = user.toString();
                            taskService.setAssignee(taskId, userId);
                        }
                    }
                }
            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }

    private boolean isMultiInstance(TaskEntity task) {
        // 获取流程定义id
        boolean flag = false;
        String processDefinitionId = task.getProcessDefinitionId();
        Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
        FlowElement flowElement = process.getFlowElement(task.getTaskDefinitionKey());
        // 根据活动id获取活动实例
        if (flowElement instanceof UserTask) {
            UserTask userTask = (UserTask) flowElement;
            if (userTask.getBehavior() instanceof ParallelMultiInstanceBehavior) {
                ParallelMultiInstanceBehavior behavior = (ParallelMultiInstanceBehavior) userTask.getBehavior();
                if (behavior != null && behavior.getCollectionExpression() != null) {
                    flag = true;
                }
            }
            if (userTask.getBehavior() instanceof SequentialMultiInstanceBehavior) {
                SequentialMultiInstanceBehavior behavior = (SequentialMultiInstanceBehavior) userTask.getBehavior();
                if (behavior != null && behavior.getCollectionExpression() != null) {
                    flag = true;
                }
            }
        }
        return flag;
    }

}

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Flowable 中,要实现会签实例任务的退回,可以通过以下步骤进行操作: 1. 首先,创建一个实现了 MultiInstanceActivityBehavior 接口的自定义活动行为类。这个类将负责处理会签实例任务的具体逻辑。 ```java public class MyMultiInstanceActivityBehavior implements MultiInstanceActivityBehavior { // 实现 MultiInstanceActivityBehavior 接口的方法 // ... } ``` 2. 在该类中,实现 `leave` 方法,该方法负责处理会签任务每个实例完成后的操作。在这个方法中,可以判断每个实例的完成情况,并根据需要进行退回操作。 ```java @Override public void leave(ActivityExecution execution) { // 判断当前实例是否需要退回 if (shouldReject(execution)) { // 获取会签任务的执行实例 ExecutionEntity multiInstanceExecution = (ExecutionEntity) execution.getParent(); // 将当前实例退回到上一步 CommandContext commandContext = Context.getCommandContext(); commandContext.getExecutionEntityManager().deleteChildExecutions(execution.getParent()); commandContext.getAgenda().planContinueMultiInstanceOperation(multiInstanceExecution); } else { // 正常离开会签任务 super.leave(execution); } } ``` 3. 将自定义的活动行为类应用到会签实例任务的流程定义中。在 BPMN 文件中,使用 `class` 属性指定自定义类的全限定名。 ```xml <userTask id="multiInstanceTask" name="Multi-Instance Task" flowable:activiti:class="com.example.MyMultiInstanceActivityBehavior" /> ``` 通过以上步骤,就可以在 Flowable实现会签实例任务的退回功能。自定义的活动行为类中的 `leave` 方法可以根据业务逻辑判断是否需要退回,并执行相应的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值