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},当agree为false时,才满足条件

  • ${}是变量表达式写法
  • 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());

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

更多


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

相关推荐
愚农搬码6 天前
Flowable 工作流中如何接入大模型 LLM 节点
llm·ai编程·工作流引擎
愚农搬码13 天前
Flowable工作流引擎如何适配国产数据库?以达梦数据库举例说明
工作流引擎
songgeb13 天前
mspec体验:基于SDD的轻量AI工作流
ai编程·工作流引擎
大龄码农有梦想13 天前
企业工作流系统如何设计用户、部门、角色、岗位、动态关系五类流程办理人?
工作流引擎·flowable·流程引擎·oa·工作流系统·选人规则·bpm平台
愚农搬码16 天前
工作流里的转办、委托和工作移交的业务语义与技术实现
工作流引擎
大龄码农有梦想16 天前
工作流中的子流程节点能否驳回到父流程?
工作流引擎·流程引擎·oa·bpm·子流程·驳回·退回
愚农搬码16 天前
工作流中的子流程节点能否驳回到父流程?
工作流引擎
愚农搬码16 天前
流程图上的回退线与运行时动态回退,应该选择哪一种?
工作流引擎
大龄码农有梦想17 天前
开源流程引擎 Camunda 如何实现任意节点跳转?
工作流引擎·流程引擎·camunda·oa·bpn·流程跳转·会签
愚农搬码20 天前
在开源流程引擎 Flowable 里如何实现任意节点跳转?
工作流引擎