别再堆 if-else 了!Flowable 工作流引擎,让你彻底告别手写审批流的烦恼

嘿,各位技术大佬们,今天我们来聊聊一个能让你在开发中“偷懒”的神器——Flowable。从此你将告别各种复杂的审批流程、状态机管理,告别手写 if-else 堆砌审批逻辑。

一、什么是 Flowable?它和 Activiti 是什么关系?

简单来说,Flowable 是从 Activiti “分支”出来的一个项目,而且是由 Activiti 的核心开发者们创建和维护的。

你可以把它们想象成两兄弟,Activiti 是哥哥,Flowable 是弟弟。在发展的过程中,弟弟 Flowable 显然更有活力,社区更活跃,功能迭代也更快,尤其是在与 Spring Boot 等现代技术栈的整合上,表现得更为出色。

二、Flowable 的“心脏”:核心组件探秘

要玩转 Flowable,得了解它的几个核心组件,它们就像是工作流引擎的“五脏六腑”,各司其职,共同协作。

  • ProcessEngine: 这是 Flowable 的绝对核心,可以理解为是所有服务的“总指挥官”。通过它,你才能获取到下面我们要说的各种 Service。

  • RepositoryService: 流程定义和部署的管理中心。比如,你想把画好的 BPMN 流程图部署到引擎中,就得靠它。它负责存储和管理流程的“蓝图”。

  • RuntimeService: 流程实例的“执行官”。当一个流程(比如,一个请假申请)被启动后,就变成了一个流程实例(Process Instance)。RuntimeService 就是用来启动、查询和管理这些正在运行中的流程实例的。

  • TaskService: 任务管理的“专家”。在一个审批流中,大部分节点都是需要人来处理的,这些就叫做用户任务(User Task)。TaskService 专门用来查询用户的待办任务、完成任务等。

  • HistoryService: “历史记录员”。所有已经完成的流程实例、任务、变量等信息,都会被它记录下来,方便你日后审计和追溯。

  • IdentityService: “身份认证专家”。虽然在实际项目中,我们通常会用自己的用户体系,但 Flowable 也提供了一套简单的用户和组管理功能。

  • FormService: “表单大师”。它可以帮你管理和渲染流程中用到的表单。

三、流程的“通用语言”:BPMN 核心元素

Flowable 使用 BPMN 2.0(业务流程模型和标记法)来定义流程。别被这个名字吓到,其实它就是一套用来画流程图的“通用语言”,而且非常直观。我们来看看最核心的几个元素:

  • 事件 (Events):

    • 开始事件 (Start Event): 每个流程的起点,用一个圆圈表示。

    • 结束事件 (End Event): 流程的终点,用一个加粗的圆圈表示。

  • 活动 (Activities):

    • 用户任务 (User Task): 需要人工处理的节点,比如“部门经理审批”。这通常是我们交互最多的地方。

    • 服务任务 (Service Task): 系统自动执行的任务,比如“发送邮件通知”。

  • 网关 (Gateways):

    • 排他网关 (Exclusive Gateway): 流程的分支点,根据条件只选择一条路径执行,就像 if-else。例如,根据请假天数决定是经理审批还是总监审批。

  • 顺序流 (Sequence Flow): 连接以上各个元素的“箭头”,定义了流程的执行顺序。

四、实战演练:设计一个最简单的审批流

光说不练假把式。我们来设计一个最简单的“请假审批”流程:员工发起申请 -> 经理审批 -> 结束。

1. 流程图 


2. 对应的 BPMN 2.0 (XML 文件)

这个 XML 文件就是流程的“蓝图”,我们会把它部署到 Flowable 引擎中。文件名可以叫 leave-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:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:flowable="http://flowable.org/bpmn"
             typeLanguage="http://www.w3.org/2001/XMLSchema"
             expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">

    <process id="leaveProcess" name="请假审批流程" isExecutable="true">

        <startEvent id="startEvent" name="开始"/>

        <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitTask"/>

        <userTask id="submitTask" name="提交请假申请" flowable:assignee="${applyUser}"/>

        <sequenceFlow id="flow2" sourceRef="submitTask" targetRef="managerApproveTask"/>

        <userTask id="managerApproveTask" name="经理审批" flowable:assignee="manager"/>

        <sequenceFlow id="flow3" sourceRef="managerApproveTask" targetRef="endEvent"/>

        <endEvent id="endEvent" name="结束"/>

    </process>

</definitions>

注意: 在 submitTask 中,flowable:assignee="${applyUser}" 表示这个任务的负责人是一个叫 applyUser 的流程变量,这个变量在我们启动流程时传入。managerApproveTask 中,我们硬编码了审批人为 manager

Flowable 与 Spring Boot 的“天作之合”

第一步:添加依赖

在你的 pom.xml 文件中,加入 Flowable 的 Spring Boot Starter。

<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.8.0</version> </dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

第二步:配置

application.properties 中,你几乎不需要做什么特殊配置,Flowable 会自动配置好数据源。如果你想看它执行的 SQL,可以加上日志配置。

Properties

# 自动创建和更新数据库表结构
spring.flowable.database-schema-update=true

第三步:把 BPMN 文件放对位置

Spring Boot Starter 会自动扫描 src/main/resources/processes 目录下的 .bpmn20.xml 文件,并在应用启动时自动部署它们。所以,把我们上面创建的 leave-process.bpmn20.xml 文件放在这个目录下。

代码实战:让流程“跑起来”!

现在,万事俱备,我们用 Java 代码来和这个流程交互。

1. 启动一个流程实例

我们可以写一个 Service 来封装流程操作。

import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
public class LeaveProcessService {

    @Autowired
    private RuntimeService runtimeService;

    @Transactional
    public void startLeaveProcess(String userId) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("applyUser", userId); // 设置发起人
        
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveProcess", variables);
        System.out.println("成功启动流程,流程实例ID: " + processInstance.getId());
    }
}

2. 查询当前用户的待办任务

当流程启动后,“提交请假申请”这个任务就创建了,并且分配给了我们传入的 userId。现在我们来查一下他的待办。

import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LeaveTaskService {

    @Autowired
    private TaskService taskService;

    public List<Task> getMyTasks(String assignee) {
        return taskService.createTaskQuery().taskAssignee(assignee).list();
    }
    
    // 完成任务
    @Transactional
    public void completeTask(String taskId) {
        taskService.complete(taskId);
        System.out.println("任务 " + taskId + " 已完成!");
    }
}

调用示例

// 假设有个 Controller
@RestController
public class LeaveController {

    @Autowired
    private LeaveProcessService processService;
    
    @Autowired
    private LeaveTaskService taskService;

    // 员工 "zhangsan" 提交申请
    @PostMapping("/leave/start")
    public String startLeave(@RequestParam String userId) {
        processService.startLeaveProcess(userId);
        return "请假流程已启动.";
    }

    // 查询 "zhangsan" 的待办
    @GetMapping("/leave/tasks")
    public List<String> getTasks(@RequestParam String userId) {
        List<Task> tasks = taskService.getMyTasks(userId);
        return tasks.stream().map(task -> "任务ID: " + task.getId() + ", 任务名称: " + task.getName()).collect(Collectors.toList());
    }
    
    // "zhangsan" 完成提交任务
    @PostMapping("/leave/complete/{taskId}")
    public String completeTask(@PathVariable String taskId) {
        taskService.completeTask(taskId);
        return "任务 " + taskId + " 已提交,等待经理审批。";
    }
}

当 “zhangsan” 完成了他的提交任务后,流程会自动流转到“经理审批”节点,此时我们用 getTasks("manager") 就能查到经理的待办任务了。

五、进阶玩法:多级审批和流程监听器

1. 多级审批:员工 -> 部门经理 -> HR

如果请假天数大于3天,需要HR审批,怎么搞?很简单,加一个排他网关就行了。

流程图 

BPMN 实现

这需要在BPMN中增加一个 exclusiveGateway,并为流出的 sequenceFlow 添加 conditionExpression

<exclusiveGateway id="daysCheck" name="检查请假天数"/>

<sequenceFlow sourceRef="managerApproveTask" targetRef="daysCheck"/>

<sequenceFlow sourceRef="daysCheck" targetRef="hrApproveTask">
  <conditionExpression xsi:type="tFormalExpression">
    <![CDATA[${approved == true && days > 3}]]>
  </conditionExpression>
</sequenceFlow>

<sequenceFlow sourceRef="daysCheck" targetRef="endEvent">
  <conditionExpression xsi:type="tFormalExpression">
    <![CDATA[${approved == true && days <= 3}]]>
  </conditionExpression>
</sequenceFlow>

<sequenceFlow sourceRef="managerApproveTask" targetRef="submitTask">
   <conditionExpression xsi:type="tFormalExpression">
    <![CDATA[${approved == false}]]>
  </conditionExpression>
</sequenceFlow>

<userTask id="hrApproveTask" name="HR审批" flowable:assignee="hr"/>

在经理审批时,需要设置流程变量 approved (true/false) 和 days

2. 流程监听器:在流程中“搞点事情”

有时候,我们想在流程的某个特定时刻(比如任务创建时、流程结束时)自动执行一些业务逻辑,比如发送通知、更新业务数据等。这时,Listener 就派上用场了。

Flowable 支持两种主要的监听器:ExecutionListener(监听流程执行路径)和 TaskListener(监听任务生命周期)。

示例:实现一个任务创建监听器

我们想在“经理审批”这个任务被创建时,自动发一条通知。

创建一个实现了 TaskListener 接口的类:

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;

public class ManagerTaskCreateListener implements TaskListener {

    @Override
    public void notify(DelegateTask delegateTask) {
        // 在这里写你的业务逻辑
        System.out.println("============== 经理审批任务创建了! ==============");
        String applyUser = (String) delegateTask.getVariable("applyUser");
        System.out.println("申请人是: " + applyUser);
        System.out.println("请经理尽快审批!发送通知...");
        // 实际场景下可能是调用钉钉、企业微信或者邮件的API
    }
}

在 BPMN 文件的 userTask 中配置这个监听器:

<userTask id="managerApproveTask" name="经理审批" flowable:assignee="manager">
  <extensionElements>
    <flowable:taskListener event="create" class="com.yourpackage.ManagerTaskCreateListener"/>
  </extensionElements>
</userTask>

这样,每次流程流转到“经理审批”节点并创建任务时,ManagerTaskCreateListener 中的 notify 方法就会被自动调用。

总结

Flowable 的功能远不止于此,它还支持并行网关、子流程、动态流程等等强大的功能。

但掌握了今天的内容,你已经足以应对 80% 的审批流需求了。剩下的 20%,就留给你在实践中继续探索和发现了。

工具是用来解放生产力的。别再让复杂的审批流拖慢你开发的脚步,是时候让 Flowable 登场,帮你“一键搞定”了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nextera-void

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

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

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

打赏作者

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

抵扣说明:

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

余额充值