一 、Flowable 的出現(xiàn)是為了什么
工作流(Workflow),是指對(duì)于一項(xiàng)業(yè)務(wù),按照規(guī)定的流程,逐級(jí)傳遞、申請(qǐng)、執(zhí)行等,并且受到了嚴(yán)格控制的一種業(yè)務(wù)過(guò)程。
BPM(Business Process Management)是指對(duì)于某項(xiàng)業(yè)務(wù)的整個(gè)生命周期進(jìn)行全面管理的一種模式,最核心的內(nèi)容包括了工作流、決策、交互等。在這些管理過(guò)程中,人員、系統(tǒng)等資源都是可以被自動(dòng)調(diào)度的,以致達(dá)到更高效、完善的管理目的。
Flowable工作流是一款基于Java的輕量級(jí)開源工作流引擎,它支持BPMN2.0規(guī)范、CMMN規(guī)范,同時(shí)也提供REST API以及JavaAPI,支持Spring,Spring Boot等框架。借助Flowable工作流,企業(yè)可以快速構(gòu)建出符合自己實(shí)際業(yè)務(wù)的工作流。
二、Flowable 的優(yōu)勢(shì)
1、輕量級(jí):Flowable工作流是一款輕量級(jí)的工作流引擎,啟動(dòng)快、體積小,且可以嵌入Java應(yīng)用中使用。
2、開放源代碼:Flowable工作流是一個(gè)開源的工作流引擎,保證企業(yè)在使用過(guò)程中不會(huì)受到第三方的監(jiān)控與限制。
3、商用友好:Flowable工作流允許企業(yè)在商業(yè)環(huán)境下進(jìn)行使用,并且提供Flowable Task一類的額外服務(wù)。
三、常見(jiàn)的Java類/實(shí)例
3.1 ProcessEngine
流程引擎實(shí)例,線程安全,一般一個(gè)工作流只需要初始化一次。
代碼示例見(jiàn)本文的 5.1 小節(jié)。
3.2 RepositoryService
可以通過(guò)流程引擎(ProcessEngine
)獲取到。使用RepositoryService
可以根據(jù)xml文件路徑創(chuàng)建一個(gè)新的部署(Deployment
),并調(diào)用 Deployment#deploy()
實(shí)際執(zhí)行。
代碼示例如下(其中xml是放在src/main/resources
中):
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("holiday-request.bpmn20.xml")
.deploy();
3.3 ProcessDefinition
流程定義實(shí)例,包含了流程的基本信息。通過(guò)RepositoryService
獲取,可以根據(jù)部署ID(Deployment
)查詢到對(duì)應(yīng)的流程的基本信息,如流程的名字。首先獲取到ProcessDefinitionQuery
實(shí)例,再根據(jù)這個(gè)Query實(shí)例去查詢1或多個(gè)流程定義實(shí)例。
代碼示例如下,查詢了1個(gè)流程定義實(shí)例:
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.singleResult();
System.out.println("Found process definition : " + processDefinition.getName());
3.4 Deployment
部署實(shí)例,通過(guò)RepositoryService獲取。
部署之后可以查詢流程定義,也可以啟動(dòng)流程實(shí)例。
部署的代碼示例見(jiàn) 3.2 小節(jié)。
PS:當(dāng)xml文件放在 src/main/resources/processes/ 里時(shí),會(huì)被自動(dòng)部署。
3.5 RuntimeService
運(yùn)行時(shí)服務(wù)實(shí)例,用來(lái)啟動(dòng)一個(gè)部署了的流程實(shí)例。
通過(guò)流程引擎獲取,啟動(dòng)時(shí)可以傳遞參數(shù)。
代碼示例如下:
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String, Object> variables = new HashMap<>();
variables.put("employee", employee);
variables.put("nrOfHolidays", nrOfHolidays);
variables.put("description", description);
ProcessInstance processInstance =
runtimeService.startProcessInstanceByKey("holidayRequest", variables);
3.6 ProcessInstance
流程實(shí)例,通過(guò) RuntimeService 啟動(dòng)一個(gè)流程獲取。
3.7 TaskService
任務(wù)服務(wù)實(shí)例,常用于查詢、完成任務(wù)。
3.8 JavaDelegate
用于定義任務(wù)執(zhí)行后自動(dòng)執(zhí)行到的一個(gè)邏輯。這是一個(gè)服務(wù)任務(wù)。
3.9 其他
1、IdentityService
用于管理(創(chuàng)建,更新,刪除,查詢……)組與用戶。
2、FormService
是可選服務(wù)。也就是說(shuō)Flowable沒(méi)有它也能很好地運(yùn)行,而不必犧牲任何功能。
3、HistoryService
暴露Flowable引擎收集的所有歷史數(shù)據(jù)。要提供查詢歷史數(shù)據(jù)的能力。
4、ManagementService
通常在用Flowable編寫用戶應(yīng)用時(shí)不需要使用。它可以讀取數(shù)據(jù)庫(kù)表與表原始數(shù)據(jù)的信息,也提供了對(duì)作業(yè)(job)的查詢與管理操作。
5、DynamicBpmnService
可用于修改流程定義中的部分內(nèi)容,而不需要重新部署它。例如可以修改流程定義中一個(gè)用戶任務(wù)的辦理人設(shè)置,或者修改一個(gè)服務(wù)任務(wù)中的類名。
四、核心數(shù)據(jù)庫(kù)表
4.1 數(shù)據(jù)庫(kù)
1、Flowable的所有數(shù)據(jù)庫(kù)表都以ACT_開頭。第二部分是說(shuō)明表用途的兩字符標(biāo)示符。服務(wù)API的命名也大略符合這個(gè)規(guī)則。
2、ACT_RE_: 'RE’代表repository。帶有這個(gè)前綴的表包含“靜態(tài)”信息,例如流程定義與流程資源(圖片、規(guī)則等)。
3、ACT_RU_: 'RU’代表runtime。這些表存儲(chǔ)運(yùn)行時(shí)信息,例如流程實(shí)例(process instance)、用戶任務(wù)(user task)、變量(variable)、作業(yè)(job)等。Flowable只在流程實(shí)例運(yùn)行中保存運(yùn)行時(shí)數(shù)據(jù),并在流程實(shí)例結(jié)束時(shí)刪除記錄。這樣保證運(yùn)行時(shí)表小和快。
4、ACT_HI_: 'HI’代表history。這些表存儲(chǔ)歷史數(shù)據(jù),例如已完成的流程實(shí)例、變量、任務(wù)等。
5、ACT_GE_: 通用數(shù)據(jù)。在多處使用。
4.2 通用數(shù)據(jù)表(2個(gè))
act_ge_bytearray:二進(jìn)制數(shù)據(jù)表,如流程定義、流程模板、流程圖的字節(jié)流文件;
act_ge_property:屬性數(shù)據(jù)表(不常用);
4.3 歷史表(8個(gè),HistoryService接口操作的表)
act_hi_actinst:歷史節(jié)點(diǎn)表,存放流程實(shí)例運(yùn)轉(zhuǎn)的各個(gè)節(jié)點(diǎn)信息(包含開始、結(jié)束等非任務(wù)節(jié)點(diǎn));
act_hi_attachment:歷史附件表,存放歷史節(jié)點(diǎn)上傳的附件信息(不常用);
act_hi_comment:歷史意見(jiàn)表;
act_hi_detail:歷史詳情表,存儲(chǔ)節(jié)點(diǎn)運(yùn)轉(zhuǎn)的一些信息(不常用);
act_hi_identitylink:歷史流程人員表,存儲(chǔ)流程各節(jié)點(diǎn)候選、辦理人員信息,常用于查詢某人或部門的已辦任務(wù);
act_hi_procinst:歷史流程實(shí)例表,存儲(chǔ)流程實(shí)例歷史數(shù)據(jù)(包含正在運(yùn)行的流程實(shí)例);
act_hi_taskinst:歷史流程任務(wù)表,存儲(chǔ)歷史任務(wù)節(jié)點(diǎn);
act_hi_varinst:流程歷史變量表,存儲(chǔ)流程歷史節(jié)點(diǎn)的變量信息;
4.4 用戶相關(guān)表(4個(gè),IdentityService接口操作的表)
act_id_group:用戶組信息表,對(duì)應(yīng)節(jié)點(diǎn)選定候選組信息;
act_id_info:用戶擴(kuò)展信息表,存儲(chǔ)用戶擴(kuò)展信息;
act_id_membership:用戶與用戶組關(guān)系表;
act_id_user:用戶信息表,對(duì)應(yīng)節(jié)點(diǎn)選定辦理人或候選人信息;
4.5 流程定義、流程模板相關(guān)表(3個(gè),RepositoryService接口操作的表)
act_re_deployment:部屬信息表,存儲(chǔ)流程定義、模板部署信息;
act_re_procdef:流程定義信息表,存儲(chǔ)流程定義相關(guān)描述信息,但其真正內(nèi)容存儲(chǔ)在act_ge_bytearray表中,以字節(jié)形式存儲(chǔ);
act_re_model:流程模板信息表,存儲(chǔ)流程模板相關(guān)描述信息,但其真正內(nèi)容存儲(chǔ)在act_ge_bytearray表中,以字節(jié)形式存儲(chǔ);
4.6 流程運(yùn)行時(shí)表(6個(gè),RuntimeService接口操作的表)
act_ru_task:運(yùn)行時(shí)流程任務(wù)節(jié)點(diǎn)表,存儲(chǔ)運(yùn)行中流程的任務(wù)節(jié)點(diǎn)信息,重要,常用于查詢?nèi)藛T或部門的待辦任務(wù)時(shí)使用;
act_ru_event_subscr:監(jiān)聽(tīng)信息表,不常用;
act_ru_execution:運(yùn)行時(shí)流程執(zhí)行實(shí)例表,記錄運(yùn)行中流程運(yùn)行的各個(gè)分支信息(當(dāng)沒(méi)有子流程時(shí),其數(shù)據(jù)與act_ru_task表數(shù)據(jù)是一一對(duì)應(yīng)的);
act_ru_identitylink:運(yùn)行時(shí)流程人員表,重要,常用于查詢?nèi)藛T或部門的待辦任務(wù)時(shí)使用;
act_ru_job:運(yùn)行時(shí)定時(shí)任務(wù)數(shù)據(jù)表,存儲(chǔ)流程的定時(shí)任務(wù)信息;
act_ru_variable:運(yùn)行時(shí)流程變量數(shù)據(jù)表,存儲(chǔ)運(yùn)行中的流程各節(jié)點(diǎn)的變量信息;
五、在SpringBoot中簡(jiǎn)單使用
以下以Mysql數(shù)據(jù)庫(kù)為例,java版本為11,開發(fā)工具使用Idea。
5.1 Flowable入門之表的生成
首先創(chuàng)建一個(gè)普通的Maven項(xiàng)目,引入依賴如下:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.8.0</version>
</dependency>
<!--mysql8-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
隨后定義 log4j.properties文件:
log4j.rootLogger=DEBUG, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
然后是一個(gè)普通的Java類,定義Main方法(這里只打印了執(zhí)行引擎實(shí)例):
package org.feng.flowable;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
public class MainFlowableClient {
/**
* 執(zhí)行引擎(現(xiàn)成安全的對(duì)象,在一個(gè)應(yīng)用中只需要初始化一次)
*/
private static final ProcessEngine processEngine;
static {
// 單機(jī)處理引擎配置信息實(shí)例
StandaloneProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration();
// 連接數(shù)據(jù)庫(kù)的信息
cfg.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC");
cfg.setJdbcUsername("root");
cfg.setJdbcPassword("123456");
cfg.setJdbcDriver("com.mysql.cj.jdbc.Driver");
// 設(shè)置了true,確保在JDBC參數(shù)連接的數(shù)據(jù)庫(kù)中,數(shù)據(jù)庫(kù)表結(jié)構(gòu)不存在時(shí),會(huì)創(chuàng)建相應(yīng)的表結(jié)構(gòu)。
cfg.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 通過(guò)配置獲取執(zhí)行引擎
processEngine = cfg.buildProcessEngine();
}
public static void main(String[] args) {
System.out.println(processEngine);
}
}
啟動(dòng)main方法后的效果是,會(huì)連接到指定的數(shù)據(jù)庫(kù),如果庫(kù)中沒(méi)有Flowable對(duì)應(yīng)數(shù)據(jù)庫(kù),或結(jié)構(gòu)發(fā)生變化,會(huì)自動(dòng)創(chuàng)建或更新表。
5.2 請(qǐng)假審批案例的實(shí)現(xiàn)
在官方手冊(cè)中有一個(gè)請(qǐng)假審批的案例,講的比較詳細(xì)。
大致流程是這樣的:發(fā)起一個(gè)開始事件,隨后一個(gè)工作流引用到用戶任務(wù)(Approve or reject request),分配給到經(jīng)理,經(jīng)理需要決定通過(guò)請(qǐng)求還是拒絕請(qǐng)求。然后使用一個(gè)排他網(wǎng)關(guān),將流程實(shí)例路由到批準(zhǔn)或者駁回。如果批準(zhǔn),則需要將申請(qǐng)注冊(cè)至某個(gè)外部系統(tǒng),并跟著另一個(gè)用戶任務(wù),將經(jīng)理的決定通知給申請(qǐng)人。當(dāng)然也可以改為發(fā)送郵件。如果駁回,則為雇員發(fā)送一封郵件通知他。
依據(jù)以上示例編寫Java代碼實(shí)現(xiàn)。
5.2.1 項(xiàng)目結(jié)構(gòu)
項(xiàng)目中對(duì)oneTask任務(wù)、請(qǐng)假流程(holidayRequest)任務(wù)做了處理。本小節(jié)只關(guān)注請(qǐng)假流程。
并且數(shù)據(jù)表前面已經(jīng)創(chuàng)建好了。
項(xiàng)目依賴使用 springboot 2.7.12 版本:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
5.2.2 application.yml
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai
username: root
password: 123456
hikari:
read-only: false
#客戶端等待連接池連接的最大毫秒數(shù)
connection-timeout: 60000
#允許連接在連接池中空閑的最長(zhǎng)時(shí)間(以毫秒為單位)
idle-timeout: 60000
#連接將被測(cè)試活動(dòng)的最大時(shí)間量
validation-timeout: 3000
#池中連接關(guān)閉后的最長(zhǎng)生命周期
max-lifetime: 60000
#最大池大小
maximum-pool-size: 60
#連接池中維護(hù)的最小空閑連接數(shù)
minimum-idle: 10
#從池返回的連接的默認(rèn)自動(dòng)提交行為。默認(rèn)值為true
auto-commit: true
#如果您的驅(qū)動(dòng)程序支持JDBC4,我們強(qiáng)烈建議您不要設(shè)置此屬性
connection-test-query: SELECT 1
#自定義連接池名稱
pool-name: myHikarCp
flowable:
# 設(shè)置了true,確保在JDBC參數(shù)連接的數(shù)據(jù)庫(kù)中,數(shù)據(jù)庫(kù)表結(jié)構(gòu)不存在時(shí),會(huì)創(chuàng)建相應(yīng)的表結(jié)構(gòu)。
database-schema-update: false
#關(guān)閉定時(shí)任務(wù)JOB
async-executor-activate: false
5.2.3 holiday-request.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: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"
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">
<!--
每一步都需要有一個(gè)id屬性,標(biāo)記當(dāng)前流程的步驟,name是可選的
當(dāng)流程開始執(zhí)行的時(shí)候,執(zhí)行過(guò)程會(huì)從startEvent開始,跟著sequenceFlow往下走
startEvent -> approveTask -> approved -> externalSystemCall -> holidayApprovedTask -> assign:employee -> approveEnd
-> reject -> sendRejectionMail -> rejectEnd
-->
<process id="holidayRequest" name="Holiday Request" isExecutable="true">
<startEvent id="startEvent"/>
<sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
<userTask id="approveTask" name="Approve or reject holiday request" flowable:candidateGroups="managers"/>
<sequenceFlow sourceRef="approveTask" targetRef="decision"/>
<exclusiveGateway id="decision"/>
<sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${approved}
]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="decision" targetRef="sendRejectionMail">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${!approved}
]]>
</conditionExpression>
</sequenceFlow>
<serviceTask id="externalSystemCall" name="Enter holidays in external system"
flowable:class="org.feng.service.task.CallExternalSystemDelegate"/>
<sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>
<userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/>
<sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
<serviceTask id="sendRejectionMail" name="Send out rejection email"
flowable:class="org.feng.service.task.SendRejectionMail"/>
<sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
<endEvent id="approveEnd"/>
<endEvent id="rejectEnd"/>
</process>
</definitions>
5.2.4 HolidayRequestDTO
package org.feng.dto;
public class HolidayRequestDTO {
/**
* 員工名
*/
private String employee;
/**
* 休假天數(shù)
*/
private Integer nrOfHolidays;
/**
* 備注
*/
private String description;
// 篇幅原因省略get/set方法,自己寫的時(shí)候要加上
}
5.2.5 HolidayRequestProcessService
package org.feng.service;
import org.feng.dto.HolidayRequestDTO;
public interface HolidayRequestProcessService {
void holidayRequest(HolidayRequestDTO holidayRequestDTO);
}
5.2.6 HolidayRequestProcessServiceImpl
package org.feng.service.impl;
import org.feng.dto.HolidayRequestDTO;
import org.feng.service.HolidayRequestProcessService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
@Service
public class HolidayRequestProcessServiceImpl implements HolidayRequestProcessService {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Override
public void holidayRequest(HolidayRequestDTO holidayRequestDTO) {
// 組裝參數(shù)
Map<String, Object> variables = new HashMap<>(8);
variables.put("employee", holidayRequestDTO.getEmployee());
variables.put("nrOfHolidays", holidayRequestDTO.getNrOfHolidays());
variables.put("description", holidayRequestDTO.getDescription());
// 啟動(dòng)流程實(shí)例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables);
// 查詢?nèi)蝿?wù),組是“managers”
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
// 打印查詢到的任務(wù)信息
System.out.println("You have " + tasks.size() + " tasks:");
for (int i = 0; i < tasks.size(); i++) {
System.out.println((i + 1) + ") " + tasks.get(i).getName());
}
// 獲取要執(zhí)行的任務(wù):查詢到的最后一個(gè)task
if (!CollectionUtils.isEmpty(tasks)) {
Task task = tasks.get(tasks.size() - 1);
Map<String, Object> processVariables = taskService.getVariables(task.getId());
System.out.println(processVariables.get("employee") + " wants " +
processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");
// 生成隨機(jī)數(shù),從而決定請(qǐng)求是通過(guò)還是拒絕
boolean approved = ThreadLocalRandom.current().nextInt(1, 10) > 5;
System.out.println(approved ? "do approved" : "do rejected");
variables = new HashMap<>();
variables.put("approved", approved);
// 執(zhí)行完成
taskService.complete(task.getId(), variables);
}
// 歷史數(shù)據(jù)
List<HistoricActivityInstance> activities =
historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstance.getId())
.finished()
.orderByHistoricActivityInstanceEndTime().asc()
.list();
for (HistoricActivityInstance activity : activities) {
System.out.println(activity.getActivityId() + " took "
+ activity.getDurationInMillis() + " milliseconds");
}
}
@PostConstruct
private void deploy() {
// 手動(dòng)部署
Deployment deployment = repositoryService.createDeployment()
// 從xml文件讀取流程
.addClasspathResource("holiday-request.bpmn20.xml")
// 執(zhí)行部署
.deploy();
// 根據(jù)部署ID獲取流程定義
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.singleResult();
// 輸出流程名
System.out.println("Found process definition : " + processDefinition.getName());
}
}
5.2.7 CallExternalSystemDelegate
package org.feng.service.task;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
public class CallExternalSystemDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
System.out.println("Calling the external system for employee "
+ execution.getVariable("employee"));
}
}
5.2.8 SendRejectionMail
package org.feng.service.task;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
public class SendRejectionMail implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
System.out.println("Send Rejection Email ");
}
}
5.2.9 HolidayRequestProcessController
package org.feng.controller;
import org.feng.dto.HolidayRequestDTO;
import org.feng.service.HolidayRequestProcessService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class HolidayRequestProcessController {
@Resource
private HolidayRequestProcessService holidayRequestProcessService;
@PostMapping("/holidayRequest")
public void holidayRequest(@RequestBody HolidayRequestDTO holidayRequestDTO) {
holidayRequestProcessService.holidayRequest(holidayRequestDTO);
}
}
5.2.10 運(yùn)行&結(jié)果展示
啟動(dòng)SpringBoot項(xiàng)目,隨后訪問(wèn)rest接口:
POST http://localhost:8080/holidayRequest
Content-Type: application/json
{
"employee": "bob",
"nrOfHolidays": 3,
"description": "就請(qǐng)假而已"
}
多次調(diào)整參數(shù),可以看到不同的結(jié)果。
部分結(jié)果展示:
請(qǐng)求通過(guò)時(shí):
You have 1 tasks:
1) Approve or reject holiday request
bob wants 3 of holidays. Do you approve this?
do approved
Calling the external system for employee bob
startEvent took 3 milliseconds
_flow_startEvent__approveTask took 0 milliseconds
approveTask took 1122 milliseconds
_flow_approveTask__decision took 0 milliseconds
_flow_decision__externalSystemCall took 0 milliseconds
decision took 1 milliseconds
externalSystemCall took 1 milliseconds
_flow_externalSystemCall__holidayApprovedTask took 0 milliseconds
請(qǐng)求拒絕時(shí):
You have 1 tasks:
1) Approve or reject holiday request
bob wants 3 of holidays. Do you approve this?
do rejected
Send Rejection Email
_flow_startEvent__approveTask took 0 milliseconds
startEvent took 0 milliseconds
approveTask took 927 milliseconds
_flow_approveTask__decision took 0 milliseconds
_flow_decision__sendRejectionMail took 0 milliseconds
decision took 2 milliseconds
_flow_sendRejectionMail__rejectEnd took 0 milliseconds
sendRejectionMail took 1 milliseconds
rejectEnd took 1 milliseconds
附錄
參考文章
Flowable工作流入門看這篇就夠了-騰訊云開發(fā)者社區(qū)-騰訊云
Flowable工作流詳解_筆記大全_設(shè)計(jì)學(xué)院
Flowable官網(wǎng)
Flowable官方用戶手冊(cè)
Flowable流程引擎入門文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-657092.html
項(xiàng)目地址
https://gitee.com/fengsoshuai/flowable-demo文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-657092.html
到了這里,關(guān)于Flowable工作流入門&完整SpringBoot案例的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!