Spring Boot 3.x + Flowable 实现加签功能

本专题将深度剖析十个工作流操作模式的定义、应用场景,及其实际设定方法。这些模式包括顺序会签、并行会签、或签、票签、抄送、驳回、分配、转办、委派和代理模式等。我们还将面对每个操作模式可能出现的问题提出解决方案,以及提供优化的策略和建议。目的是帮助读者全面掌握和应用工作流逻辑,解决实际问题并提升业务效率。

1. 定义和理解加签

加签(Sign-up)是一种在工作流中,当某个节点的审批操作需要增加额外的参与者时,通过动态地添加新审批人的操作。这个过程通常用于复杂的审批操作场景,如需要额外的审核或重新确认等。

2. 加签模式的应用场景

加签模式经常用于以下场景:

  • 管理层审批:在初步审批后,需要增加高层领导或其他部门的审批。

  • 异常情况处理:在某些业务异常的情况下,需要增加特殊的审核流程。

  • 动态调整审批人:根据业务规则调整参与审批的人员名单。

3. 实际操作:如何实现加签模式
环境配置

首先确保你有一个Spring Boot 3.x的项目,并已经集成了Flowable。以下是基本的pom.xml依赖:

<dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-spring-boot-starter-process</artifactId>
    </dependency>
    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-spring-boot-starter</artifactId>
    </dependency>
</dependencies>
基本代码实现

实际的示例代码分为以下几个部分:

配置Flowable

在Spring Boot中配置Flowable:

@Configuration
public class FlowableConfig {

    @Bean
    public SpringProcessEngineConfiguration springProcessEngineConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager) {
        SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration();
        config.setDataSource(dataSource);
        config.setTransactionManager(transactionManager);
        config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        config.setAsyncExecutorActivate(false);
        return config;
    }
}
定义流程模型

创建一个新的bpmn流程文件,比如add_sign_process.bpmn20.xml,基本流程如下:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:flowable="http://flowable.org/bpmn"
             targetNamespace="Examples">
    <process id="addSignProcess" name="Add Sign Process">
        <startEvent id="startEvent" name="Start"></startEvent>
        <userTask id="initialApproval" name="Initial Approval" flowable:assignee="approver1"></userTask>
        <exclusiveGateway id="approvalDecision" name="Approval Decision"></exclusiveGateway>
        <sequenceFlow id="toAddSign" sourceRef="initialApproval" targetRef="approvalDecision"></sequenceFlow>
        <sequenceFlow id="toAddSignTask" sourceRef="approvalDecision" targetRef="addSignTask"></sequenceFlow>
        <userTask id="addSignTask" name="Add Sign Task" flowable:assignee="${assignee}"></userTask>
        <sequenceFlow id="toEnd" sourceRef="addSignTask" targetRef="endEvent"></sequenceFlow>
        <endEvent id="endEvent" name="End"></endEvent>
    </process>
</definitions>
创建服务类

创建一个简单的服务类来启动流程,并实现加签功能:

@Service
public class WorkflowService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    /**
     * 启动加签流程
     */
    public void startProcess() {
        runtimeService.startProcessInstanceByKey("addSignProcess");
    }

    /**
     * 执行加签操作
     * @param taskId 任务ID
     * @param newAssignee 加签人员
     */
    public void addSign(String taskId, String newAssignee) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null && "initialApproval".equals(task.getTaskDefinitionKey())) {
            // 当前任务加签
            taskService.setAssignee(taskId, newAssignee);
        }
    }
}
创建控制器

提供一个REST接口来触发加签操作:

@RestController
@RequestMapping("/process")
public class WorkflowController {

    @Autowired
    private WorkflowService workflowService;

    @PostMapping("/start")
    public ResponseEntity<String> startProcess() {
        workflowService.startProcess();
        return ResponseEntity.ok("Process started");
    }

    @PostMapping("/addSign")
    public ResponseEntity<String> addSign(@RequestParam String taskId, @RequestParam String newAssignee) {
        workflowService.addSign(taskId, newAssignee);
        return ResponseEntity.ok("Added sign for task");
    }
}
4. 遇到的问题和解决策略

遇到的问题和解决策略

在实现加签过程中,可能会遇到操作复杂性、流程状态管理、并发性处理等多个层面的问题。以下是对常见问题及解决策略的更深入讲解。

问题 1:任务重复分配

描述:在加签过程中,有可能出现任务被重复分配给同一用户的情况。重复分配不仅会导致资源浪费,还可能引起审批的混乱和延迟。

解决策略:

任务检查:在分配任务之前,需要检查当前任务是否已被分配。这可以通过TaskService进行查询。

 public void addSign(String taskId, String newAssignee) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null && "initialApproval".equals(task.getTaskDefinitionKey())) {
            // 检查当前任务分配情况
            if (!newAssignee.equals(task.getAssignee())) {
                // 当前任务加签
                taskService.setAssignee(taskId, newAssignee);
            }
        }
    }

日志记录:记录每次任务分配和加签的操作,便于事后审计和分析。通过任务历史管理服务(HistoryService)保留操作记录。

HistoryService historyService = processEngine.getHistoryService();
    HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery()
        .taskId(taskId).singleResult();
    // 记录历史任务操作
问题 2:流程状态异常

描述:在多次加签操作中,可能导致流程状态不一致。例如,某个节点被重复加签但实际审批人未变更,导致流程卡住或异常。

解决策略:

事务管理:确保加签操作在事务管理中执行,以保证流程状态的一致性。可以通过Spring的事务管理来实现。

  @Transactional
    public void addSign(String taskId, String newAssignee) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null && "initialApproval".equals(task.getTaskDefinitionKey())) {
            if (!newAssignee.equals(task.getAssignee())) {
                taskService.setAssignee(taskId, newAssignee);
            }
        }
    }

状态检查和回滚:在执行加签操作前,检查当前流程状态是否正常。如果加签操作失败,能够自动进行状态回滚以保持数据一致性。

 try {
        // 执行加签操作
        performAddSign(taskId, newAssignee);
    } catch (Exception e) {
        // 发生异常,进行状态回滚
        transactionManager.rollback(status);
        throw new RuntimeException("加签操作失败", e);
    }
问题 3:并发性处理

描述:在高并发环境中,多用户同时执行加签操作,可能导致数据竞争和不一致问题。

解决策略:

乐观锁机制:在数据库层面使用乐观锁,防止多个事务同时操作同一条数据。

 // 启用乐观锁
    @Version
    private int version;

重试机制:在并发操作失败时,增加重试机制,通过多次尝试完成操作,提高成功率。

 public void performAddSignWithRetry(String taskId, String newAssignee) {
        int retries = 3;
        while (retries > 0) {
            try {
                performAddSign(taskId, newAssignee);
                return;
            } catch (OptimisticLockingException e) {
                retries--;
                if (retries == 0) {
                    throw new RuntimeException("加签操作失败,重试次数达到上限", e);
                }
            }
        }
    }

问题 4:动态调整参与者

描述:根据实际情况实时调整审批人是加签中常见的需求,但这也增加了流程设计和实现的复杂性。

解决策略:

业务规则引擎:利用业务规则引擎(如Drools),根据动态业务规则来自动分配和调整审批人。

 // 规则文件定义
    rule "Adjust Approver"
    when
        $task : Task(taskDefinitionKey == "initialApproval")
    then
        // 动态调整审批人
        assignApprover($task);
    end

事件驱动机制:采用事件驱动架构,通过事件总线(如Spring Event)动态监听和处理加签请求。

 @EventListener
    public void handleAddSignEvent(AddSignEvent event) {
        performAddSign(event.getTaskId(), event.getNewAssignee());
    }

通过以上深入的策略和实现,可以更好地解决加签过程中遇到的问题,确保流程的稳定性和可靠性。

优化加签模式的建议
  • 动态分配策略:根据业务需求实现更灵活的加签策略,如角色、部门等。

  • 日志记录和监控:记录每次加签操作,方便审计和回溯。

  • 自动化测试:为加签功能设计自动化测试用例,确保其稳定性和可靠性。

总结

通过Spring Boot 3.x + Flowable实现加签功能,可以有效地提升工作流程的灵活性和可控性。在实际应用中,需根据业务需求进行定制和优化,确保功能的稳定和高效。如有疑问或深入探讨,欢迎进一步交流和分享经验。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

missterzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值