这篇文章虽然发布较早,但仍然是了解 Flowable 的一篇优秀入门资料,对于学习 Flowable 与 Spring 的集成也很有参考价值,因此在这里重新分享。
版本说明 :本文示例基于 Flowable 6.5.0 和 MySQL Connector/J 8.0.11 。部分界面、依赖坐标及配置项可能与新版本不同,实际使用时请结合对应版本的官方文档进行调整。
转载来源 :原博客地址
1. 什么是 BPMN 1.1 工作流(引擎)介绍 在任何行业和企业中,都有各种各样的流程,例如:
请假流程
报销流程
入职流程
离职流程
出差流程
其他需要多人协作的流程
即使你没有设计过工作流,每天也很可能在使用各种流程。
工作流引擎本质上就是用代码实现 UML 流程图中的各个步骤。
凡是需要多个人或多个部门按照先后顺序逐级审批的业务,都可以使用工作流来完成。
1.2 为什么要用 BPMN
业务流程模型与标记法(Business Process Model and Notation,BPMN)定义了描述流程的基本符号,以及这些图元如何组合成业务流程图(Business Process Diagram)。
对于流程控制,一种比较初级的实现方式是在业务代码中加入 status 状态字段来维护流程状态,审批人也可能直接使用硬编码。这种方式在流程较简单时实现很快,但从长远来看会出现几个问题:
流程健壮性差 :一旦出现人员变动或组织结构调整,就需要修改代码,维护成本较高。
流程无法复用 :组织出现新的工作流程时,往往需要重新开发一套代码,开发成本很高。
流程与业务代码耦合 :流程逻辑和业务逻辑互相混杂,不符合单一职责与解耦原则。
1.3 认识 BPMN 基础元素 BPMN 2.0 的核心主要包括以下四类基础元素:
元素
英文
主要作用
流对象
Flow Objects
描述流程中发生的事件、活动和分支
数据
Data
描述流程使用、产生或存储的数据
连接对象
Connecting Objects
连接流程元素并表达流转关系
泳道
Swimlanes
按参与者或职责对活动进行分组
1.3.1 流对象(Flow Objects) 流对象是定义业务流程的主要图形元素,包括事件、活动和网关三类。
1. 事件(Events)
事件指业务流程运行过程中发生的事情,分为:
开始事件 :表示一个流程的开始。
中间事件 :发生在开始与结束事件之间,并会影响流程处理。
结束事件 :表示流程结束。
2. 活动(Activities)
活动包括任务和子流程两类。子流程的图形下方中间会增加一个小加号(+),用于与普通任务区分。
3. 网关(Gateways)
网关用于表示流程的分支与合并:
排他网关 :只有一条路径会被选择。
并行网关 :所有路径都会被同时选择。
包容网关 :可以同时执行多条路径,也可以在网关上设置条件。
事件网关 :专门为中间捕获事件设置,可以配置多个输出流,分别指向不同的中间捕获事件。流程执行到事件网关后会进入等待状态,直到捕获相应事件后才继续执行。
1.3.2 数据(Data) 数据主要通过四种元素表示:
数据对象(Data Objects)
数据输入(Data Inputs)
数据输出(Data Outputs)
数据存储(Data Stores)
1.3.3 连接对象(Connecting Objects) 流对象彼此连接,或与其他信息建立联系,主要有三种方式:
顺序流 :使用带实心箭头的实线表示,用于指定活动执行的顺序。
消息流 :使用带箭头的虚线表示,用于描述两个独立业务参与者(业务实体或业务角色)之间发送和接收消息的过程。
关联 :使用带箭头的点线表示,用于将相关数据、文本和其他人工信息与流对象联系起来,也可用于展示活动的输入和输出。
1.3.4 泳道(Swimlanes) 泳道用于对主要建模元素进行分组,将活动划分到不同的可视化类别中,以描述不同参与者的责任与职责。
1.4 BPMN 实例 实例 1:拍卖服务 BPMN 模板
实例 2:书籍销售流程 BPMN
2. Flowable 简介 Flowable 是 BPMN 的一种 Java 软件实现。除了 BPMN 流程引擎,Flowable 还包括 DMN 决策表、CMMN Case 管理引擎,以及用户管理、微服务 API 等一系列功能,因此也可以把它看作一个完整的流程服务平台。
2.1 Flowable 部署 2.1.1 下载 访问 Flowable Engine Releases 并选择需要的版本。本文使用的是 6.5.0 。
2.1.2 部署 WAR 包 下载并解压后,wars 目录中共有 5 个 WAR 包:
flowable-admin:后台管理。
flowable-idm:用户与用户组权限管理。
flowable-modeler:流程定义管理。
flowable-rest:流程引擎对外提供的 API 接口。
flowable-task:用户任务管理。
将这些 WAR 包放入 Tomcat 的 webapps 目录,然后运行 tomcat/bin/startup.bat 启动 Tomcat。首次启动和解压通常需要等待一段时间。
2.1.3 修改配置文件 所有 WAR 包解压后,在各项目的 WEB-INF/classes 目录中找到配置文件。例如:
1 webapps/flowable-admin/WEB-INF/classes/application-dev.properties
1. 修改 application-dev.properties
将数据库连接改为自己的地址。数据库名 flowable 需要自行创建,再执行 flowable-6.5.0.zip 中 database/create/all 目录下的 SQL 脚本完成建表。
1 2 3 4 5 6 7 8 9 10 11 spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.datasource.url =jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username =root spring.datasource.password =root flowable.admin.app.server-config.process.port =9999 flowable.admin.app.server-config.cmmn.port =9999 flowable.admin.app.server-config.app.port =9999 flowable.admin.app.server-config.dmn.port =9999 flowable.admin.app.server-config.form.port =9999 flowable.admin.app.server-config.content.port =9999
2. 修改 flowable-default.properties
修改 webapps/flowable-admin/WEB-INF/classes/flowable-default.properties,主要是将数据库连接切换为 MySQL:
注意 :
需要在每个项目的 WEB-INF/lib 目录下添加 MySQL 驱动包。
高版本 MySQL 驱动需要配置部分必需的连接参数。本文使用 mysql-connector-java-8.0.11.jar,连接地址如下:
1 jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 server.port =9988 server.servlet.context-path =/flowable-admin management.endpoints.jmx.unique-names =true spring.aop.proxy-target-class =false spring.aop.auto =false spring.application.name =flowable-ui-admin spring.liquibase.enabled =false spring.servlet.multipart.max-file-size =10MB spring.banner.location =classpath:/org/flowable/spring/boot/flowable-banner.txt spring.jmx.default-domain =${spring.application.name} management.endpoints.web.exposure.include =* management.endpoint.health.show-details =when_authorized management.endpoint.health.roles =access-admin flowable.common.app.role-prefix =spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.datasource.url =jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username =root spring.datasource.password =root
所有项目的配置修改完成后,关闭之前运行的 Tomcat,再重新启动。
2.1.4 访问 Flowable 应用 等待所有应用正常启动后,可以通过以下地址访问:
2.2 Flowable 数据表 Flowable 的数据库表通常以 ACT_ 开头,服务 API 的命名也大体遵循这一规则。
表名前缀
含义
说明
ACT_RE_
Repository
存储流程定义、流程资源(图片、规则等)静态信息
ACT_RU_
Runtime
存储流程实例、用户任务、变量、作业等运行时信息
ACT_HI_
History
存储已完成的流程实例、变量、任务等历史数据
ACT_GE_
General
存储在多处使用的通用数据
Flowable 只在流程实例运行期间保存运行时数据,并在流程实例结束时删除对应运行时记录,从而让运行时表保持较小的数据量和较高的查询速度。
2.2.1 通用数据表(2 个)
act_ge_bytearray:二进制数据表,例如流程定义、流程模板和流程图的字节流文件。
act_ge_property:Flowable 相关的基础信息,例如各个模块使用的版本信息,日常业务中较少直接使用。
2.2.2 历史表(8 个) 这些表主要由 HistoryService 接口操作:
act_hi_actinst:历史节点表,存放流程实例运行经过的各个节点信息,包括开始、结束等非任务节点。
act_hi_attachment:历史附件表,存放历史节点上传的附件信息,较少使用。
act_hi_comment:历史意见表。
act_hi_detail:历史详情表,存储节点运行的部分详细信息,较少使用。
act_hi_identitylink:历史流程人员表,存储流程各节点的候选人、候选组和办理人信息,常用于查询某人或某部门的已办任务。
act_hi_procinst:历史流程实例表,存储流程实例历史数据,也包含正在运行的流程实例。
act_hi_taskinst:历史流程任务表,存储历史任务节点。
act_hi_varinst:流程历史变量表,存储流程历史节点的变量信息。
2.2.3 用户相关表(4 个) 这些表主要由 IdentityService 接口操作:
act_id_group:用户组信息表,对应节点选择的候选组信息。
act_id_info:用户扩展信息表。
act_id_membership:用户与用户组关系表。
act_id_user:用户信息表,对应节点选择的办理人或候选人信息。
2.2.4 流程定义、流程模板相关表(3 个) 这些表主要由 RepositoryService 接口操作:
act_re_deployment:部署信息表,存储流程定义和模板的部署信息。
act_re_procdef:流程定义信息表,存储流程定义的描述信息;真正的流程定义内容以字节形式存储在 act_ge_bytearray 表中。
act_re_model:流程模板信息表,存储流程模板的描述信息;真正的模板内容以字节形式存储在 act_ge_bytearray 表中。
2.2.5 流程运行时表(6 个) 这些表主要由 RuntimeService 接口操作:
act_ru_task:运行时流程任务节点表,存储运行中流程的任务节点信息。该表非常重要,常用于查询人员或部门的待办任务。
act_ru_event_subscr:事件监听信息表,较少直接使用。
act_ru_execution:运行时流程执行实例表,记录运行中流程各个分支的信息;当没有子流程时,其数据通常与 act_ru_task 表数据一一对应。
act_ru_identitylink:运行时流程人员表,常用于查询人员或部门的待办任务。
act_ru_job:运行时定时任务数据表,存储流程的定时任务信息。
act_ru_variable:运行时流程变量数据表,存储运行中流程各节点的变量信息。
3. Flowable 流程设计器的使用 3.1 新建流程图
注意 :流程的 key 最好不要包含中文。后续流程部署、启动和跳转都可能用到它,因此不要定义得过于随意。
3.2 根据业务需求绘制流程图 3.2.1 节点分类 常用节点包括开始节点、用户任务节点和结束节点。
3.2.2 节点名称 可以直接在“名称”处填写,也可以双击节点输入名称。
3.2.3 分配用户 该配置只针对用户任务节点。
可以为节点分配审批人。由于 Flowable 自带的组织结构与实际业务系统的组织架构可能存在差异,因此在简单场景中通常先使用固定值。
3.2.4 任务监听器 任务监听器只针对用户任务节点。
监听器类型:
create:任务被创建时执行。
assignment:任务被签收或分配时执行。
complete:任务完成时执行。
delete:任务被删除时执行。
常见使用场景:
create:直接为用户节点设置审批人,只适用于办理人固定或候选人固定的场景。如果用户节点的办理人不固定,可以通过 create 任务监听器动态设置。
complete:当用户任务完成后需要抄送或触发其他业务动作时,可以使用 complete 任务监听器。
不同类型任务监听器的配置方式基本相同。
3.2.5 多实例 Flowable 支持为一个节点创建多个实例。通俗地说,流程图中虽然只画了一个用户节点,但通过多实例配置,可以在流程运行时为该节点创建多个实例,类似于循环,循环次数取决于配置的基数或集合。
多实例支持两种执行方式:
串行(Sequential) :多个实例按顺序执行。
并行(Parallel) :多个实例同时执行,不强调先后顺序。
默认情况下,两者都需要所有实例完成后,该节点才算结束。
3.2.6 流程线 1. 流条件配置
审批流中最常见的结果是通过和驳回,这时需要为对应的流程线设置流转条件。Flowable 流条件以表达式的方式存在。
2. 跳过表达式
跳过表达式的配置方式与流条件类似。流程启动后,当传入的流程变量满足表达式要求时,会自动跳过对应节点。
3.2.7 常用网关 1. 排他网关
通过排他网关的流程线只能有一条被选择。
排他网关支持设置默认出口。流程执行后,如果其他流程线的条件都返回 false,则会进入默认流程线。
2. 并行网关
只有所有需要经过并行网关的任务流都完成后,流程才会进入下一步。
3.3 保存流程图
保存后,流程图相关数据会保存在 act_de_model 表中。每次更新并保存后,流程定义的版本号都会加 1。
3.4 下载流程图
4. 在 Spring Boot 中使用 Flowable 4.1 基本用法 4.1.1 引入依赖 在 pom.xml 中加入 Web、JDBC、MySQL 和 Flowable 等相关依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-jdbc</artifactId > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.11</version > </dependency > <dependency > <groupId > org.flowable</groupId > <artifactId > flowable-spring-boot-starter</artifactId > <version > 6.5.0</version > </dependency > <dependency > <groupId > org.flowable</groupId > <artifactId > flowable-json-converter</artifactId > <version > 6.5.0</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > <dependency > <groupId > com.alibaba.fastjson2</groupId > <artifactId > fastjson2</artifactId > <version > 2.0.1</version > </dependency >
4.1.2 配置 application.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server: port: 9999 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false username: root password: root flowable: async-executor-activate: false database-schema-update: true
4.1.3 绘制 BPMN 流程图 这里以学生请假流程为例。学生先发起请假申请,再由老师审核。老师审核通过后,根据请假天数进行判断:
请假天数大于 2 天:流转到校长处审核,然后结束流程。
请假天数不大于 2 天:直接结束流程。
部署流程需要一个 .bpmn20.xml 文件,可以手动编辑,也可以借助流程设计工具创建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 <?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" xmlns:bpmndi ="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc ="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi ="http://www.omg.org/spec/DD/20100524/DI" typeLanguage ="http://www.w3.org/2001/XMLSchema" expressionLanguage ="http://www.w3.org/1999/XPath" targetNamespace ="http://www.flowable.org/processdef" > <process id ="StudentLeave" name ="学生请假流程" isExecutable ="true" > <startEvent id ="start" name ="开始" flowable:formFieldValidation ="true" > </startEvent > <userTask id ="apply" name ="请假申请" flowable:assignee ="${studentUser}" flowable:formFieldValidation ="true" > <extensionElements > <modeler:initiator-can-complete xmlns:modeler ="http://flowable.org/modeler" > <![CDATA[false]]> </modeler:initiator-can-complete > </extensionElements > </userTask > <userTask id ="teacherPass" name ="老师审批" flowable:candidateGroups ="teacher" flowable:formFieldValidation ="true" > </userTask > <exclusiveGateway id ="judgeTask" name ="判断是否大于2天" > </exclusiveGateway > <endEvent id ="end" name ="结束" > </endEvent > <userTask id ="principalPass" name ="校长审批" flowable:candidateGroups ="principal" flowable:formFieldValidation ="true" > </userTask > <sequenceFlow id ="principalCheck" name ="通过" sourceRef ="principalPass" targetRef ="end" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${outcome == '通过'}]]> </conditionExpression > </sequenceFlow > <sequenceFlow id ="principalNotPassFlow" name ="驳回" sourceRef ="principalPass" targetRef ="apply" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${outcome == '驳回'}]]> </conditionExpression > </sequenceFlow > <sequenceFlow id ="teacherPassFlow" name ="通过" sourceRef ="teacherPass" targetRef ="judgeTask" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${outcome == '通过'}]]> </conditionExpression > </sequenceFlow > <sequenceFlow id ="teacherNotPassFlow" name ="驳回" sourceRef ="teacherPass" targetRef ="apply" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${outcome == '驳回'}]]> </conditionExpression > </sequenceFlow > <sequenceFlow id ="startFlow" sourceRef ="start" name ="流程开始" targetRef ="apply" > </sequenceFlow > <sequenceFlow id ="applyFlow" sourceRef ="apply" name ="申请流程" targetRef ="teacherPass" > </sequenceFlow > <sequenceFlow id ="judgeLess" name ="小于2天" sourceRef ="judgeTask" targetRef ="end" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${day <= 2}]]> </conditionExpression > </sequenceFlow > <sequenceFlow id ="judgeMore" name ="大于2天" sourceRef ="judgeTask" targetRef ="principalPass" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${day > 2}]]> </conditionExpression > </sequenceFlow > </process > <bpmndi:BPMNDiagram id ="BPMNDiagram_StudentLeave" > <bpmndi:BPMNPlane bpmnElement ="StudentLeave" id ="BPMNPlane_StudentLeave" > <bpmndi:BPMNShape bpmnElement ="start" id ="BPMNShape_start" > <omgdc:Bounds height ="30.0" width ="30.0" x ="100.0" y ="163.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="apply" id ="BPMNShape_apply" > <omgdc:Bounds height ="80.0" width ="100.00000000000003" x ="229.9708609547486" y ="138.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="teacherPass" id ="BPMNShape_teacherPass" > <omgdc:Bounds height ="80.0" width ="99.99999999999994" x ="436.9446358140222" y ="138.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="judgeTask" id ="BPMNShape_judgeTask" > <omgdc:Bounds height ="40.0" width ="40.0" x ="645.0" y ="158.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="end" id ="BPMNShape_end" > <omgdc:Bounds height ="28.0" width ="28.0" x ="795.0" y ="164.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="principalPass" id ="BPMNShape_principalPass" > <omgdc:Bounds height ="80.0" width ="100.0" x ="615.0" y ="280.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNEdge bpmnElement ="judgeLess" id ="BPMNEdge_judgeLess" > <omgdi:waypoint x ="684.5095911949685" y ="178.43356643356645" > </omgdi:waypoint > <omgdi:waypoint x ="795.0000829380081" y ="178.04860604497966" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="principalNotPassFlow" id ="BPMNEdge_principalNotPassFlow" > <omgdi:waypoint x ="615.0" y ="320.0" > </omgdi:waypoint > <omgdi:waypoint x ="279.9708609547486" y ="320.0" > </omgdi:waypoint > <omgdi:waypoint x ="279.9708609547486" y ="217.95000000000002" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="judgeMore" id ="BPMNEdge_judgeMore" > <omgdi:waypoint x ="665.4326241134752" y ="197.51043586109145" > </omgdi:waypoint > <omgdi:waypoint x ="665.1411660777385" y ="280.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="teacherNotPassFlow" id ="BPMNEdge_teacherNotPassFlow" > <omgdi:waypoint x ="486.9446358140222" y ="138.0" > </omgdi:waypoint > <omgdi:waypoint x ="486.9446358140222" y ="98.8874737106014" > </omgdi:waypoint > <omgdi:waypoint x ="279.9708609547486" y ="98.8874737106014" > </omgdi:waypoint > <omgdi:waypoint x ="279.9708609547486" y ="138.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="principalCheck" id ="BPMNEdge_principalCheck" > <omgdi:waypoint x ="714.9499999999886" y ="319.64664310954066" > </omgdi:waypoint > <omgdi:waypoint x ="806.5" y ="319.0" > </omgdi:waypoint > <omgdi:waypoint x ="808.7518112709728" y ="191.94785201600882" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="applyFlow" id ="BPMNEdge_applyFlow" > <omgdi:waypoint x ="329.9208609546613" y ="178.0" > </omgdi:waypoint > <omgdi:waypoint x ="436.9446358140222" y ="178.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="teacherPassFlow" id ="BPMNEdge_teacherPassFlow" > <omgdi:waypoint x ="536.8946358140222" y ="178.0" > </omgdi:waypoint > <omgdi:waypoint x ="645.0" y ="178.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="startFlow" id ="BPMNEdge_startFlow" > <omgdi:waypoint x ="129.94999932842546" y ="178.0" > </omgdi:waypoint > <omgdi:waypoint x ="229.970860954748" y ="178.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > </bpmndi:BPMNPlane > </bpmndi:BPMNDiagram > </definitions >
将 XML 保存为 学生请假流程.bpmn20.xml,并复制到项目的 resources/processes 目录下。如果没有 processes 文件夹,可以自行创建。
Flowable 会自动部署 processes 目录中的流程模型。也可以通过修改 flowable.process-definition-location-prefix 的默认值,重新指定流程定义目录。
项目启动后,可以通过 RepositoryService 查询已部署的模型。查询结果不为空,就表示模型部署成功。如果应用与 Flowable Modeler 使用同一个数据库,也可以在 Flowable Admin 管理平台中部署流程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Autowired private RepositoryService repositoryService;@Test public void testProcessDefinition () { List<ProcessDefinition> processList = repositoryService.createProcessDefinitionQuery().list(); for (ProcessDefinition processDefinition : processList) { log.info( "ProcessDefinition name = {}, deploymentId = {}" , processDefinition.getName(), processDefinition.getDeploymentId() ); } }
4.1.4 员工请假流程示例 下面再提供一个“员工请假流程”,可用于测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 <?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" xmlns:bpmndi ="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc ="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi ="http://www.omg.org/spec/DD/20100524/DI" typeLanguage ="http://www.w3.org/2001/XMLSchema" expressionLanguage ="http://www.w3.org/1999/XPath" targetNamespace ="http://www.flowable.org/processdef" > <process id ="holidayRequest" name ="Holiday Request" isExecutable ="true" > <startEvent id ="startEvent" > </startEvent > <sequenceFlow id ="sequenceFlow-3fa7af74-df9a-4d3a-b0eb-10b20e7dc202" sourceRef ="startEvent" targetRef ="approveTask" > </sequenceFlow > <userTask id ="approveTask" name ="经理通过或驳回申请" > </userTask > <sequenceFlow id ="sequenceFlow-d9127dc0-158f-4169-b61b-99226ffe8494" sourceRef ="approveTask" targetRef ="decision" > </sequenceFlow > <exclusiveGateway id ="decision" > </exclusiveGateway > <serviceTask id ="externalSystemCall" name ="系统记录申请天数" flowable:class ="org.flowable.CallExternalSystemDelegate" > </serviceTask > <sequenceFlow id ="sequenceFlow-6232f578-3975-4d7e-81f2-43b242d33ebd" sourceRef ="externalSystemCall" targetRef ="holidayApprovedTask" > </sequenceFlow > <userTask id ="holidayApprovedTask" name ="员工查看申请通过" > </userTask > <sequenceFlow id ="sequenceFlow-29fd3375-9bcb-42f2-bb6f-63ae1f98813a" sourceRef ="holidayApprovedTask" targetRef ="approveEnd" > </sequenceFlow > <serviceTask id ="sendRejectionMail" name ="发送驳回邮件" flowable:class ="org.flowable.SendRejectionMail" > </serviceTask > <sequenceFlow id ="sequenceFlow-b390b442-2411-44a9-96eb-3c129d4c8408" sourceRef ="sendRejectionMail" targetRef ="rejectEnd" > </sequenceFlow > <endEvent id ="approveEnd" > </endEvent > <endEvent id ="rejectEnd" > </endEvent > <sequenceFlow id ="sequenceFlow-6f21d3e2-2e49-4b00-9aae-0b71d861a177" name ="驳回" sourceRef ="decision" targetRef ="sendRejectionMail" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${!approved}]]> </conditionExpression > </sequenceFlow > <sequenceFlow id ="sequenceFlow-2470619b-fa36-440b-a231-b7bd226c23bb" name ="通过" sourceRef ="decision" targetRef ="externalSystemCall" > <conditionExpression xsi:type ="tFormalExpression" > <![CDATA[${approved}]]> </conditionExpression > </sequenceFlow > </process > <bpmndi:BPMNDiagram id ="BPMNDiagram_holidayRequest" > <bpmndi:BPMNPlane bpmnElement ="holidayRequest" id ="BPMNPlane_holidayRequest" > <bpmndi:BPMNShape bpmnElement ="startEvent" id ="BPMNShape_startEvent" > <omgdc:Bounds height ="30.0" width ="30.0" x ="0.0" y ="95.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="approveTask" id ="BPMNShape_approveTask" > <omgdc:Bounds height ="60.0" width ="100.0" x ="80.0" y ="80.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="decision" id ="BPMNShape_decision" > <omgdc:Bounds height ="40.0" width ="40.0" x ="230.0" y ="90.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="externalSystemCall" id ="BPMNShape_externalSystemCall" > <omgdc:Bounds height ="60.0" width ="100.0" x ="320.0" y ="1.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="holidayApprovedTask" id ="BPMNShape_holidayApprovedTask" > <omgdc:Bounds height ="60.0" width ="100.0" x ="470.0" y ="1.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="sendRejectionMail" id ="BPMNShape_sendRejectionMail" > <omgdc:Bounds height ="60.0" width ="100.0" x ="320.0" y ="160.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="approveEnd" id ="BPMNShape_approveEnd" > <omgdc:Bounds height ="28.0" width ="28.0" x ="620.0" y ="16.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNShape bpmnElement ="rejectEnd" id ="BPMNShape_rejectEnd" > <omgdc:Bounds height ="28.0" width ="28.0" x ="505.0" y ="175.0" > </omgdc:Bounds > </bpmndi:BPMNShape > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-2470619b-fa36-440b-a231-b7bd226c23bb" id ="BPMNEdge_sequenceFlow-2470619b-fa36-440b-a231-b7bd226c23bb" > <omgdi:waypoint x ="250.0" y ="90.0" > </omgdi:waypoint > <omgdi:waypoint x ="250.0" y ="31.0" > </omgdi:waypoint > <omgdi:waypoint x ="319.99999999999284" y ="31.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-3fa7af74-df9a-4d3a-b0eb-10b20e7dc202" id ="BPMNEdge_sequenceFlow-3fa7af74-df9a-4d3a-b0eb-10b20e7dc202" > <omgdi:waypoint x ="29.949998618355412" y ="110.0" > </omgdi:waypoint > <omgdi:waypoint x ="80.0" y ="110.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-6232f578-3975-4d7e-81f2-43b242d33ebd" id ="BPMNEdge_sequenceFlow-6232f578-3975-4d7e-81f2-43b242d33ebd" > <omgdi:waypoint x ="419.95000000000005" y ="31.0" > </omgdi:waypoint > <omgdi:waypoint x ="470.0" y ="31.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-b390b442-2411-44a9-96eb-3c129d4c8408" id ="BPMNEdge_sequenceFlow-b390b442-2411-44a9-96eb-3c129d4c8408" > <omgdi:waypoint x ="419.949999999997" y ="189.66442953020135" > </omgdi:waypoint > <omgdi:waypoint x ="505.00030595247523" y ="189.0936221647077" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-d9127dc0-158f-4169-b61b-99226ffe8494" id ="BPMNEdge_sequenceFlow-d9127dc0-158f-4169-b61b-99226ffe8494" > <omgdi:waypoint x ="179.9499999999898" y ="110.0" > </omgdi:waypoint > <omgdi:waypoint x ="230.0" y ="110.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-29fd3375-9bcb-42f2-bb6f-63ae1f98813a" id ="BPMNEdge_sequenceFlow-29fd3375-9bcb-42f2-bb6f-63ae1f98813a" > <omgdi:waypoint x ="569.9499999999988" y ="31.0" > </omgdi:waypoint > <omgdi:waypoint x ="582.0" y ="31.0" > </omgdi:waypoint > <omgdi:waypoint x ="582.0" y ="31.0" > </omgdi:waypoint > <omgdi:waypoint x ="620.0025321198765" y ="30.268220825690175" > </omgdi:waypoint > </bpmndi:BPMNEdge > <bpmndi:BPMNEdge bpmnElement ="sequenceFlow-6f21d3e2-2e49-4b00-9aae-0b71d861a177" id ="BPMNEdge_sequenceFlow-6f21d3e2-2e49-4b00-9aae-0b71d861a177" > <omgdi:waypoint x ="250.0" y ="129.9375468164794" > </omgdi:waypoint > <omgdi:waypoint x ="250.0" y ="190.0" > </omgdi:waypoint > <omgdi:waypoint x ="319.99999999997794" y ="190.0" > </omgdi:waypoint > </bpmndi:BPMNEdge > </bpmndi:BPMNPlane > </bpmndi:BPMNDiagram > </definitions >
4.1.5 测试流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 @Autowired private RuntimeService runtimeService;@Autowired private TaskService taskService;@Autowired private HistoryService historyService;@Test public void testFlow () { Map<String, Object> map = new HashMap <>(); map.put("day" , 2 ); map.put("studentUser" , "小明" ); ProcessInstance studentLeave = runtimeService.startProcessInstanceByKey("StudentLeave" , map); Task task = taskService.createTaskQuery() .processInstanceId(studentLeave.getId()) .singleResult(); taskService.complete(task.getId()); List<Task> teacherTaskList = taskService.createTaskQuery() .taskCandidateGroup("teacher" ) .list(); Map<String, Object> teacherMap = new HashMap <>(); teacherMap.put("outcome" , "通过" ); for (Task teacherTask : teacherTaskList) { taskService.complete(teacherTask.getId(), teacherMap); } List<Task> principalTaskList = taskService.createTaskQuery() .taskCandidateGroup("principal" ) .list(); Map<String, Object> principalMap = new HashMap <>(); principalMap.put("outcome" , "通过" ); for (Task principalTask : principalTaskList) { taskService.complete(principalTask.getId(), principalMap); } List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery() .processInstanceId(studentLeave.getId()) .finished() .orderByHistoricActivityInstanceEndTime() .asc() .list(); for (HistoricActivityInstance activity : activities) { System.out.println(activity.getActivityName()); } }
当请假天数 day 为 2 时,打印结果如下:
1 2 3 4 5 6 7 8 9 开始 流程开始 请假申请 申请流程 老师审批 通过 判断是否大于2天 小于2天 结束
将请假天数 day 改为 5,打印结果如下:
1 2 3 4 5 6 7 8 9 10 11 开始 流程开始 请假申请 申请流程 老师审批 通过 判断是否大于2天 大于2天 校长审批 通过 结束
4.2 Flowable 常用配置项
以下配置清单基于本文使用的旧版本,主要用于帮助理解各模块的职责。请根据实际启用的引擎选择所需配置,不要不加区分地复制全部内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 flowable.check-process-definitions =true flowable.custom-mybatis-mappers =flowable.custom-mybatis-x-m-l-mappers =flowable.database-schema =flowable.database-schema-update =true flowable.db-history-used =true flowable.deployment-name =SpringBootAutoDeployment flowable.history-level =flowable.process-definition-location-prefix =classpath*:/processes/ flowable.process-definition-location-suffixes =**.bpmn20.xml,**.bpmn flowable.process.definition-cache-limit =-1 flowable.process.enable-safe-xml =true flowable.process.servlet.load-on-startup =-1 flowable.process.servlet.name =Flowable BPMN Rest API flowable.process.servlet.path =/process-api flowable.process.async-executor-activate =true flowable.process.async.executor.async-job-lock-time-in-millis =300000 flowable.process.async.executor.default-async-job-acquire-wait-time-in-millis =10000 flowable.process.async.executor.default-queue-size-full-wait-time-in-millis =0 flowable.process.async.executor.default-timer-job-acquire-wait-time-in-millis =10000 flowable.process.async.executor.max-async-jobs-due-per-acquisition =1 flowable.process.async.executor.retry-wait-time-in-millis =500 flowable.process.async.executor.timer-lock-time-in-millis =300000 flowable.cmmn.deploy-resources =true flowable.cmmn.deployment-name =SpringBootAutoDeployment flowable.cmmn.enable-safe-xml =true flowable.cmmn.enabled =true flowable.cmmn.resource-location =classpath*:/cases/ flowable.cmmn.resource-suffixes =**.cmmn,**.cmmn11,**.cmmn.xml,**.cmmn11.xml flowable.cmmn.servlet.load-on-startup =-1 flowable.cmmn.servlet.name =Flowable CMMN Rest API flowable.cmmn.servlet.path =/cmmn-api flowable.cmmn.async-executor-activate =true flowable.cmmn.async.executor.async-job-lock-time-in-millis =300000 flowable.cmmn.async.executor.default-async-job-acquire-wait-time-in-millis =10000 flowable.cmmn.async.executor.default-queue-size-full-wait-time-in-millis =0 flowable.cmmn.async.executor.default-timer-job-acquire-wait-time-in-millis =1000 flowable.cmmn.async.executor.max-async-jobs-due-per-acquisition =1 flowable.cmmn.async.executor.retry-wait-time-in-millis =500 flowable.cmmn.async.executor.timer-lock-time-in-millis =300000 flowable.content.enabled =true flowable.content.servlet.load-on-startup =-1 flowable.content.servlet.name =Flowable Content Rest API flowable.content.servlet.path =/content-api flowable.content.storage.create-root =true flowable.content.storage.root-folder =flowable.dmn.deploy-resources =true flowable.dmn.deployment-name =SpringBootAutoDeployment flowable.dmn.enable-safe-xml =true flowable.dmn.enabled =true flowable.dmn.history-enabled =true flowable.dmn.resource-location =classpath*:/dmn/ flowable.dmn.resource-suffixes =**.dmn,**.dmn.xml,**.dmn11,**.dmn11.xml flowable.dmn.servlet.load-on-startup =-1 flowable.dmn.servlet.name =Flowable DMN Rest API flowable.dmn.servlet.path =/dmn-api flowable.dmn.strict-mode =true flowable.form.deploy-resources =true flowable.form.deployment-name =SpringBootAutoDeployment flowable.form.enabled =true flowable.form.resource-location =classpath*:/forms/ flowable.form.resource-suffixes =**.form flowable.form.servlet.load-on-startup =-1 flowable.form.servlet.name =Flowable Form Rest API flowable.form.servlet.path =/form-api flowable.idm.enabled =true flowable.idm.password-encoder =flowable.idm.servlet.load-on-startup =-1 flowable.idm.servlet.name =Flowable IDM Rest API flowable.idm.servlet.path =/idm-api flowable.idm.ldap.attribute.email =flowable.idm.ldap.attribute.first-name =flowable.idm.ldap.attribute.group-id =flowable.idm.ldap.attribute.group-name =flowable.idm.ldap.attribute.group-type =flowable.idm.ldap.attribute.last-name =flowable.idm.ldap.attribute.user-id =flowable.idm.ldap.base-dn =flowable.idm.ldap.cache.group-size =-1 flowable.idm.ldap.custom-connection-parameters =flowable.idm.ldap.enabled =false flowable.idm.ldap.group-base-dn =flowable.idm.ldap.initial-context-factory =com.sun.jndi.ldap.LdapCtxFactory flowable.idm.ldap.password =flowable.idm.ldap.port =-1 flowable.idm.ldap.query.all-groups =flowable.idm.ldap.query.all-users =flowable.idm.ldap.query.groups-for-user =flowable.idm.ldap.query.user-by-full-name-like =flowable.idm.ldap.query.user-by-id =flowable.idm.ldap.search-time-limit =0 flowable.idm.ldap.security-authentication =simple flowable.idm.ldap.server =flowable.idm.ldap.user =flowable.idm.ldap.user-base-dn =flowable.mail.server.default-from =flowable@localhost flowable.mail.server.host =localhost flowable.mail.server.password =flowable.mail.server.port =1025 flowable.mail.server.use-ssl =false flowable.mail.server.use-tls =false flowable.mail.server.username =management.endpoint.flowable.cache.time-to-live =0ms management.endpoint.flowable.enabled =true
5. Flowable 常用 API Flowable 整体通过 ProcessEngine 进行操作。无论使用什么框架接入流程,都需要通过 ProcessEngine 提供的服务来处理,因此可以把它理解为 Flowable 对外公开的门面。
类图如下:
关系图如下:
API
作用
formService.getStartFormKey()
获取启动表单的 Key
formService.getRenderedStartForm()
查询渲染后的启动表单
5.2 RepositoryService RepositoryService 提供编辑和发布审批流程的 API,主要负责模型管理与流程定义。
5.2.1 查询模型与流程定义 1 2 3 4 5 6 7 8 9 10 11 repositoryService.createXXXQuery(); repositoryService.createModelQuery().list(); repositoryService.createProcessDefinitionQuery().list(); repositoryService.createXXXXQuery().XXXKey(XXX);
5.2.2 模型与部署操作
API
作用
repositoryService.getModel()
获取模型
repositoryService.saveModel()
保存模型
repositoryService.deleteModel()
删除模型
repositoryService.createDeployment().deploy()
部署模型
repositoryService.getModelEditorSource()
获取模型 JSON 数据的 UTF-8 字节数据
repositoryService.getModelEditorSourceExtra()
获取 PNG 格式的附加图像数据
原文作者在实际测试中发现,getModel() 获取模型时可能存在问题,使用时建议结合具体 Flowable 版本验证。
5.2.3 流程定义操作
API
作用
repositoryService.getProcessDefinition(processDefinitionId)
获取流程定义的详细信息
repositoryService.activateProcessDefinitionById()
激活流程定义
repositoryService.suspendProcessDefinitionById()
挂起流程定义
repositoryService.deleteDeployment()
删除部署及相关流程定义
repositoryService.getProcessDiagram()
获取流程定义图片流
repositoryService.getResourceAsStream()
获取流程定义 XML 流
repositoryService.getBpmnModel(processDefinitionId)
获取 BPMN 模型对象,可用于绘制当前流程图
5.2.4 流程定义授权
API
作用
repositoryService.getIdentityLinksForProcessDefinition()
获取流程定义授权列表
repositoryService.addCandidateStarterGroup()
新增候选启动组授权
repositoryService.addCandidateStarterUser()
新增候选启动用户授权
repositoryService.deleteCandidateStarterGroup()
删除候选启动组授权
repositoryService.deleteCandidateStarterUser()
删除候选启动用户授权
5.3 RuntimeService RuntimeService 用于处理正在运行的流程实例。
API
作用
runtimeService.createProcessInstanceBuilder().start()
发起流程
runtimeService.deleteProcessInstance()
删除正在运行的流程实例
runtimeService.suspendProcessInstanceById()
挂起流程实例
runtimeService.activateProcessInstanceById()
激活流程实例
runtimeService.getVariables(processInstanceId)
获取流程变量,也就是表单中填写的值
runtimeService.getActiveActivityIds(processInstanceId)
获取当前活动节点 ID,可用于绘制流程当前状态
终止流程可以使用流程状态变更构造器:
1 2 3 runtimeService.createChangeActivityStateBuilder() .moveExecutionsToSingleActivityId(executionIds, endId) .changeState();
5.4 HistoryService 用户发起审批后会生成流程实例。HistoryService 用于处理历史流程实例,其中既包括已完成的流程,也包括尚未完成但已经产生历史数据的流程。
API
作用
historyService.createHistoricProcessInstanceQuery().list()
查询历史流程实例列表,包括未完成的流程实例
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult()
根据 ID 查询单个历史流程实例
historyService.deleteHistoricProcessInstance()
删除历史流程实例
historyService.deleteHistoricTaskInstance(taskId)
删除历史任务实例
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list()
查询流程实例的历史节点列表,可用于绘制流程执行轨迹
遍历历史流程实例后,可以结合历史变量查询接口获取流程中的表单信息。
如果要处理正在运行的流程实例,请使用 RuntimeService。
5.5 TaskService TaskService 用于处理流程实例中各个用户任务节点的审批。
5.5.1 任务流转与审批
API
作用
taskService.createTaskQuery().list()
查询待办任务列表
taskService.createTaskQuery().taskId(taskId).singleResult()
查询待办任务详情
taskService.saveTask(task)
修改并保存任务
taskService.setAssignee()
设置审批人
taskService.addComment()
添加审批备注
taskService.complete(taskId)
完成当前任务
taskService.getProcessInstanceComments(processInstanceId)
查看流程实例的审批人与审批意见
taskService.delegateTask(taskId, delegateUserId)
委派任务
taskService.claim(taskId, userId)
认领任务
taskService.unclaim(taskId)
取消认领
taskService.complete(taskId, completeVariables)
携带流程变量完成任务
5.5.2 任务授权
API
作用
taskService.addGroupIdentityLink()
新增用户组任务授权
taskService.addUserIdentityLink()
新增用户任务授权
taskService.deleteGroupIdentityLink()
删除用户组任务授权
taskService.deleteUserIdentityLink()
删除用户任务授权
5.6 ManagementService ManagementService 主要用于执行自定义命令:
1 managementService.executeCommand(new ClassA ());
ClassA 需要实现 Command 接口并重写 execute 方法。在自定义命令中,可以通过以下方式获取 RepositoryService:
1 2 3 4 5 ProcessEngineConfiguration processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext); RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
也可以获取流程定义实体管理器:
1 2 3 4 5 ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext); ProcessDefinitionEntityManager processDefinitionEntityManager = processEngineConfiguration.getProcessDefinitionEntityManager();
ProcessDefinitionEntityManager 提供 findById、findLatestProcessDefinitionByKey、findLatestProcessDefinitionByKeyAndTenantId 等方法。
5.7 IdentityService IdentityService 用于获取和保存身份信息。下面是两个常见查询:
API
作用
identityService.createUserQuery().userId(userId).singleResult()
获取审批用户的详细信息
identityService.createGroupQuery().groupId(groupId).singleResult()
获取审批组的详细信息