工作流flowable实现撤回

Flowable是一个开源的工作流引擎,可以实现工作流程的自动化管理,包括任务分配、流转、审批等。如果需要实现撤回功能,可以考虑以下方案:

在流程定义中添加一个撤回节点,允许任务的发起人在任务未被处理前撤回任务。当发起人选择撤回任务时,任务将被撤回至撤回节点,由发起人修改后再次提交任务。

在任务表中添加一个状态字段,记录任务的状态,例如待处理、已处理、已撤回等。当任务被撤回时,将任务状态改为已撤回,同时在任务历史表中记录撤回记录,方便后续查询。

在任务节点中添加一个监听器,监听任务状态的变化,当任务状态变为已撤回时,将任务撤回至上一个处理节点或撤回节点,由处理人重新处理任务。

需要注意的是,在实现撤回功能时需要考虑到安全性和合理性,例如撤回的时间限制、撤回次数限制等。

以下是一个简单的Java代码示例,演示如何实现流程任务的撤回功能:
1.添加撤回节点

<userTask id="cancelTask" name="撤回任务" flowable:assignee="${initiator}">
  <extensionElements>
    <flowable:formProperty id="reason" name="撤回原因" type="string" required="true" />
  </extensionElements>
</userTask>

其中 i n i t i a t o r 表示任务的发起人, {initiator}表示任务的发起人, initiator表示任务的发起人,{reason}表示撤回原因,可以根据需要修改。
2.更新任务状态
在任务表中添加一个状态字段,例如:

@Entity
@Table(name = "flowable_task")
public class FlowableTask {
    // 其他字段省略
    @Column(name = "status")
    private String status = "pending"; // 任务状态,默认为待处理

    // getter 和 setter 方法省略
}

3.监听任务状态变化
在任务节点中添加一个监听器,例如:

<userTask id="task1" name="任务1" flowable:assignee="${assignee}">
  <extensionElements>
    <flowable:executionListener event="end" class="com.example.TaskStatusListener" />
  </extensionElements>
</userTask>

其中com.example.TaskStatusListener是一个实现org.flowable.engine.delegate.ExecutionListener接口的监听器,例如:

@Component
public class TaskStatusListener implements ExecutionListener {
    @Autowired
    private TaskService taskService;

    @Override
    public void notify(DelegateExecution execution) {
        String taskId = execution.getVariable("taskId");
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null) {
            String status = (String) execution.getVariable("status");
            if (status != null) {
                task.setStatus(status); // 更新任务状态
                taskService.saveTask(task); // 保存任务
            }
        }
    }
}

4.实现撤回操作
在业务代码中实现撤回操作,例如:

@Service
public class TaskService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskRepository taskRepository;

    public void cancelTask(String taskId, String reason) {
        // 获取当前任务
        FlowableTask task = taskRepository.findById(taskId).orElseThrow(() -> new RuntimeException("任务不存在"));
        if (!task.getStatus().equals("pending")) {
            throw new RuntimeException("任务已被处理,不能撤回");
        }
        // 创建撤回任务
        Map<String, Object> variables = new HashMap<>();
        variables.put("initiator", task.getAssignee());
        variables.put("reason", reason);
        runtimeService.createProcessInstanceModification(task.getProcessInstanceId())
                .cancelActivityInstanceId(task.getExecutionId())
                .startBeforeActivity("cancelTask")
                .setVariables(variables)
                .execute();
        // 更新任务状态
        task.setStatus("cancelled");
        taskRepository.save(task);
    }
}

其中taskId为需要撤回的任务ID,reason为撤回原因,具体实现可根据业务场景和需求进行调整。

### Flowable 中的任务撤回最佳实践 在 Flowable 工作流引擎中,任务撤回可以通过多种方式实现。为了确保操作的安全性和灵活性,通常建议采用以下方法之一: #### 方法一:使用历史数据和自定义服务任务 通过保存流程实例的历史状态,在需要撤回时可以恢复到之前的版本。这涉及到创建一个自定义的服务任务来管理这些历史记录。 ```java // 创建一个新的 Java 类作为自定义 Service Task 来处理任务撤销逻辑 public class TaskRevertServiceTask implements JavaDelegate { @Override public void execute(DelegateExecution execution) throws Exception { String processInstanceId = (String)execution.getVariable("processInstanceId"); // 获取当前活动 ID 和前序活动ID HistoricActivityInstance currentActivity = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId).unfinished().singleResult(); List<HistoricActivityInstance> previousActivities = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceEndTime().asc() .listPage(0, 1); if (!previousActivities.isEmpty()) { HistoricActivityInstance prevActInst = previousActivities.get(0); runtimeService.setVariableLocal(execution.getId(), "revertedFrom", currentActivity.getActivityId()); runtimeService.addComment(execution.getId(), null, "Task reverted from "+currentActivity.getActivityName()+" to "+prevActInst.getActivityName()); // 跳转至指定节点 ProcessDefinitionEntity definition = ((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition(currentActivity.getProcessDefinitionId()); ActivityImpl targetActivity = definition.findActivity(prevActInst.getActivityId()); execution.setCurrentFlowElement(targetActivity); } } } ``` 此代码片段展示了如何编写一个 `JavaDelegate` 接口的具体实现类[^1],用于捕获并存储必要的上下文信息以便后续能够返回至上一步骤。 #### 方法二:利用事件监听器机制 另一种更灵活的方法是借助于 Flowable 提供的事件监听器功能。可以在特定条件下触发相应的动作,比如当某个条件满足时自动跳回到上一步或任意其他步骤。 ```xml <!-- 定义 BPMN 流程中的 User Task --> <userTask id="taskA" name="Step A"> <!-- 添加边界事件监听器 --> <boundaryEvent id="cancelBoundaryEvt" attachedToRef="taskA" cancelActivity="true"> <errorEventDefinition errorRef="ERROR_CANCEL"/> </boundaryEvent> </userTask> <!-- 自定义错误处理器 --> <bpmn:error code="ERROR_CANCEL">Cancel Task Event Triggered.</bpmn:error> ``` 上述 XML 片段说明了如何设置带有取消行为的边界事件监听器[^2]。一旦关联的任务被中断,则会抛出预定义好的异常从而激活对应的补偿措施。 无论采取哪种方案都应充分考虑实际应用场景下的需求特点,并结合项目具体情况做出合理的选择。值得注意的是,以上两种策略并非互斥而是互补关系;实践中可以根据复杂度适当组合运用两者优势达成最优解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值