Flowable工作流引擎最简教程

写在前面


最近几个月做了一些工作流相关的需求,也看了不少视频和文档资料。给我的感觉是,概念太多,网上也缺少一些对复杂组件的案例使用。

其实几个需求做下来,我发现常用的组件就几个:开始事件、结束事件、顺序流、互斥网关。最多再加上服务任务、任务监听器和执行监听器。

也是因为我处理的工作流程比较简单,并没有涉及到太复杂应用,诸如:边界事件、中间事件、子流程等。

基于此原则,才有了这个最简教程。即,使用常用的组件来实现一个流程,避免复杂的概念讲解。

如果刚好你的需求和我相似,又或者你仅仅是想了解一下工作流引擎,那么本文很适合你。

本文旨在怎么使用工作流引擎进行流程设计、启动、流转等,省略了工作流引擎前后端集成环节,默认你已经集成了。如果你想把工作流引擎集成进自己系统,可以参考其他资料

工作流引擎是什么


对应用层面来说,就是:数据表 + api实现的流程流转服务,其他暂时不需要关注。

怎么用


这里包含几个步骤:

  1. 设计流程
  2. 部署流程
  3. 启动流程实例
  4. 操作流程实例

不好理解的话,拿面向对象来类比,分别对应

  1. 设计类
  2. 创建类 Class A {}
  3. 创建类实例 A a = new A()
  4. 使用类实例 a.getData()、a.setData()

下面,一步步来说

1、设计流程

这种图,大家想必很熟悉了,没接触过应该也可以看懂。其实工作流引擎的流程,也和这个相似

转化过来,就是下面这个样子

你可以用这个画:BPMN Editor | bpmn-js modeler Demo | demo.bpmn.io

这样看,也没有什么大的不同,就是换了换组件

这两个圆圈就是:开始事件、结束事件

标志着流程的开始结束

这种正菱形 的,叫做网关

里面一个X 的,是互斥网关 ,表示要么走左边,要么走右边

一个矩形 ,称为任务

左上角有个人的图标 的,叫做用户任务

对了,还有带箭头的线 ,叫做顺序流,用于连接各个组件

掌握了这些,就能开始进行流程设计了

我们拿老生常谈的请假流程举例子吧

  • 员工发起请假,启动流程
  • 请假不超过3天,组长审批;不超过3天,经理审批
  • 审批同意,考勤人员归档,结束流程;不同意,直接结束流程

上面提到的流程绘制工具bpmn.js 一般需要集成进系统,我们直接使用集成好的bpmn.js

生产环境一般会集成bpmn.js 进行流程设计,可以参考实现 RuoYi-flowable: 基于RuoYi-vue + flowable 6.x 的工作流管理平台

流程图画好了,但还没有完全画好。问题在于:工作流引擎怎么知道要走哪条路的?

通过:互斥网关 + 条件流转路径

我们给互斥网关 出发的顺序流 ,设置为条件流转路径,即满足条件才走这条路

并且设置表达式为${agree == false},当agreefalse时,才满足条件

  • ${}是变量表达式写法
  • agree称为流程变量

那么问题来了,要是我不设置,或者设置成一样的,会是什么结果?

当然是报错,正如一个人不能同时向左转和向右转

所以要求我们,各个分叉路口,都得写好条件表达式,并且覆盖全面

流程设计的正确与否,直接影响流程的运行结果,部署前请仔细检查

还有个问题:用户任务指定给了谁?

我们选中用户任务 ,就可以配置任务执行人 ,也叫做候选人

生产环境中,一般有以下几种类型:

  • 指定人
  • 指定角色
  • 指定部门
  • 变量表达式

分配到人,活才有人干不是吗?

至此,请假流程 设计好了,这里对流程设计的步骤做个小结

  • 放置开始事件、结束事件
  • 有条件分支,放置流程网关,设置其流出顺序流为条件流转路径
  • 放置用户任务,配置候选人
  • 保存流程

2、部署流程

可设计为:保存时自动部署,或者点击部署。这个与工作流引擎的集成方式有关

3、启动流程实例

集成好的工作流引擎,一般支持点击发起流程 ,即创建流程实例

还是拿上面的请假流程 举例:小明需要请假,填写了请假单并保存

流程实例的启动可以多种方法:

  • 前端实现:保存请假单 接口调用成功,调用发起流程接口
  • 后端实现:保存请假单 业务后,同步或者异步使用工作流引擎API,发起流程

前端实现异常情况下,会有事务问题 ,而后端实现,我们可以通过事务分布式事务等方式来避免

可参考

java 复制代码
@Transactional(rollbackFor = Exception.class)
public String startInstance(
    String processDefinitionKey, 
    Map<String, Object> variables) 
{
    UserDetail user = SecurityUser.getUser();
    // 启动流程用户
    identityService.setAuthenticatedUserId(user.getId().toString());

    // 流程参数
    variables.put("nextUserId", user.getId().toString());

    String businessKey = (String) variables.get("businessKey");

    // 获取key对应的最新版本流程id
    String processDefinitionId = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).latestVersion().singleResult().getId();

    // 启动流程
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables);

    return processInstance.getProcessInstanceId();
}

启动前,可以将请假天数,写入流程变量variables

流程实例启动后,我们需要保存实例ID到业务数据中,方便进行后续的调用

4、 使用流程实例

拿到实例ID 后,我们便能操作流程实例的流转结束

流程的流转

java 复制代码
public boolean auditByInstanceId(FlowProcessInstanceAuditDTO req){
    // 查找任务
    Task task = taskService.createTaskQuery()
            .processInstanceId(req.getProcessInstanceId())
            .singleResult();

    if (task == null) {
        log.error("任务不存在");
        return false;
    }

    //添加意见
    if (StringUtils.isNotBlank(req.getComment())) {
        taskService.addComment(task.getId(), task.getProcessInstanceId(), req.getComment());
    }

    //流程变量
    Map<String, Object> variables = new HashMap<>();
    // 控制流程分支
    variables.put("agree", req.getApprove());
    variables.put("nextUserId", req.getNextUserId());

    // 签收任务
    taskService.claim(task.getId(), SecurityUser.getUserId().toString());

    //提交任务
    taskService.complete(task.getId(), variables);

    return true;
}

流程的结束

java 复制代码
public void endByInstanceId(String instanceId) {
    // 根据流程实例ID获取流程实例
    ProcessInstance instance = runtimeService.createProcessInstanceQuery()
            .processInstanceId(instanceId)
            .singleResult();

    if (instance == null) {
        throw new RenException("流程实例不存在");
    }

    runtimeService.deleteProcessInstance(instanceId, "流程终止");
}

可以看到,通过表达式方式引入的条件流程路径用户任务候选人 ,我们均可以使用流程变量进行填入,即

java 复制代码
    variables.put("agree", req.getApprove());
    variables.put("nextUserId", req.getNextUserId());

使用前端集成好的流程表单填入也可,但是缺乏灵活性

更多


如果你需要学习更多工作流引擎的知识,可以使用如下资料

相关推荐
葫芦和十三16 天前
解构 Coze 工作流引擎:从可视化画布到可中断执行的源码之旅
workflow·工作流引擎·coze
人生都在赌20 天前
为什么我放弃了Zapier,选择n8n来构建AI Agent工作流?
agent·ai编程·工作流引擎
二闹2 个月前
Java I/O 与 NIO 演进之路:如何优化你的文件与网络操作性能
后端·性能优化·工作流引擎
sylwair2 个月前
在 Dokploy 上升级 n8n 的经验分享
自动化运维·工作流引擎
Young55662 个月前
还不了解工作流吗(基础篇)?
java·workflow·工作流引擎
laughing9983 个月前
独立域名,免费服务器,无限活跃工作流--n8n免费部署
google·产品·工作流引擎
我姓谭却弹不死你3 个月前
9、Activiti-任务(Task)的相关操作
activiti·工作流引擎·任务管理·业务流程管理
餘yuqn5 个月前
activiti 项目运行时找不到数据表 ACT_GE_PROPERTY
服务器·后端·工作流引擎
FlowGram5 个月前
FlowGram 简介:开源前端流程搭建引擎
工作流引擎