购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.3 启动第一个完整流程

一个最基本的Flowable流程开发过程是,设计确认流程内容,使用流程设计器建模流程,导入或通过接口方式将流程定义XML文件部署到流程引擎上,通过流程引擎提供的服务类执行流程实例,自动保存流程数据到数据库,如图2.8所示。

图2.8 Flowable流程开发过程

Flowable官网教程提供了一个简单的流程运行例子,它非常适合初学者完整认识和使用Flowable流程引擎。

我们将实战的例子是一个简单的请假(Holiday Request)流程,具体如下。

● 员工(Employee)申请假期。

● 经理(Manager)批准或拒绝申请。

● 我们将模拟在某个外部系统中注册申请,并向员工发送一封包含结果的电子邮件。

2.3.1 创建项目

打开IDEA,在菜单栏中单击File菜单,依次单击New→Project...→Maven选项,创建一个新的Maven项目,如图2.9所示。

图2.9 创建一个新的Maven项目

单击Next按钮进入下一个界面,填入项目名(Name)为“flowable-test”,GroupId和ArtifactId默认即可,如图2.10所示。

图2.10 填入项目名

单击Finish按钮,这样就创建了一个新的Maven项目。

2.3.2 创建流程引擎

为项目添加3个依赖,具体如下。

(1)Flowable流程引擎:使我们可以创建一个ProcessEngine流程引擎对象,并访问Flowable API。

(2)数据库:本实例中使用H2数据库。当Flowable引擎运行流程实例时,需要使用数据库来存储运行时的数据与历史数据。

(3)日志框架:Flowable使用SLF4J作为内部日志框架。在本实例中,我们使用log4j作为SLF4J的实现。

在pom.xml文件中添加下列内容:

log4j需要配置文件。在src/main/resources文件夹下添加log4j.properties文件,并写入下列内容:

注意,关于log4j的远程代码执行漏洞问题,因为其影响的范围是apache log4j 2.x<=2.14.1版本,所以上面的日志版本是安全的。

有时候,依赖JAR文件无法自动获取,可以右键点击项目,并依次选择Maven→Reload Project选项以强制手动刷新。

创建一个新的Java类,并添加标准的main()方法:

我们要做的第一件事是实例化ProcessEngine流程引擎实例。首先创建一个ProcessEngineConfiguration实例,并配置数据库JDBC连接,然后由ProcessEngineConfiguration创建ProcessEngine实例,具体代码如下:

注意,H2数据库的数据在应用重启后会消失,如果要永久保存数据,需要切换为持久化数据库并修改连接参数和驱动。

现在可以运行应用了。在IDEA中最简单的方法是右键点击类文件,选择Run'HolidayRequest.main()'选项,如图2.11所示。

应用成功运行,这样就可以看到关于引擎启动和创建数据库表的信息日志了,如图2.12所示。

图2.11 运行应用

图2.12 应用运行结果

现在已经启动了一个流程引擎,是时候给它提供一个流程了!

2.3.3 创建流程定义文件

我们即将构建的是一个简单的请假流程,在Flowable术语中,将其称为流程定义,可以使用流程定义启动多个流程实例。流程定义被视为流程执行的蓝图,在这个实例中,定义了请假涉及的各个步骤,一个流程实例对应员工的一个请假申请。

下面,我们将要使用的请假流程做如图2.13所示的定义。为了清晰起见,对图2.13中的几个要点做以下说明。

(1)启动流程需要提供一些信息,如申请人名字、请假时长及说明等。

(2)左侧的圆圈是启动事件,为一个流程实例的起点。

图2.13 请假流程

(3)第一个矩形是用户任务(User Task),是流程中用户必须手动操作的步骤。在这个实例里,经理需要批准或拒绝申请。

(4)根据经理的决定,独占网关(Exclusive Gateway)(带“X”符号的菱形)会将流程实例路由至批准或拒绝路径。

(5)如果申请获得批准,则需要先将申请注册到某个外部系统,接着继续执行另一个用户任务,向申请人通知经理的决定。

(6)如果申请被拒绝,将向申请人发送一封电子邮件作为通知。

注意,一般来说,这样的流程定义使用可视化建模工具建立,如Flowable Designer(Eclipse插件)或Flowable Web Modeler(Web应用)。IDEA没有官方提供的可视化插件,可选插件为Flowable BPMN visualizer。

将下面的XML文件保存在src/main/resources文件夹下名为holiday-request.bpmn20.xml的文件中。为了突出重点内容,已省略XML文件定义头部内容:

每一个步骤(在BPMN 2.0术语中称为活动)都有一个ID属性,是在XML文件中唯一的标识符。所有活动可以设置一个可选名字,从而增加流程图的可读性。

这些活动由顺序流(Sequence Flow)连接,在流程图中表示为一个有向箭头。在执行流程实例时,执行将按照顺序流从启动事件流向下一个活动。

离开独占网关的顺序流很特殊:都有一个以表达式(Expression)形式定义的条件(Condition)。当流程实例的执行到达这个网关时,将解析条件,采用第一个解析为true的条件。这就是独占的含义——只选择一个。

这里用作条件的表达式为“${approved}”,这是${approved==true}的简写。变量approved被称为流程变量(Process Variable)。

现在我们已经有了流程BPMN 2.0 XML文件,接下来需要将它部署(Deploy)到Flowable引擎中。

2.3.4 部署流程定义文件

从ProcessEngine对象中获取RepositoryService服务类,将流程定义文件部署到Flowable引擎。通过使用RepositoryService服务类的API,以XML文件路径的方式创建一个新的部署,并调用deploy()方法执行部署:

我们可以通过API查询验证已经部署在引擎中的流程定义,使用RepositoryService服务类创建的ProcessDefinitionQuery流程定义查询对象来实现:

2.3.5 启动流程实例

由于已经在流程引擎中部署了流程定义,因此可以使用该流程定义作为蓝图启动流程实例。

要启动流程实例,需要提供一些初始流程变量。一般来说,当某个流程被触发时,可以通过用户输入的表单或者REST API来获取这些流程变量信息。在本实例中,为了简单起见,我们使用Java.util.Scanner类在命令行上输入一些数据:

接下来,我们使用RuntimeService服务类启动一个流程实例。收集的数据以一个Java.util.Map实例传递,其中的键就是之后用于获取变量的标识符。这个流程实例使用key启动,即BPMN 2.0 XML文件中设置的ID属性,在这个实例中是holidayRequest:

当流程实例启动后,会创建一个执行并将其放在启动事件上。从这里开始,这个执行沿着顺序流移动到经理审批的用户任务,并执行用户任务行为。此行为将在数据库中创建一个任务,稍后可以使用查询找到该任务。当执行到用户任务时,流程处于等待状态,引擎会停止任何操作并返回API调用:

2.3.6 查询与完成任务

这里还没有为用户任务指派办理人,我们希望第一个任务指派给“managers”组,第二个用户任务指派给请假申请的提交人。因此需要为第一个任务添加candidateGroups属性,修改流程XML配置文件:

为第二个任务添加assignee属性。注意,我们没有像上面的“managers”组一样使用静态值,而是基于流程实例启动时传递的流程变量动态赋值:

要获得实际的任务列表,需要通过TaskService服务类创建一个TaskQuery,下面配置这个查询只返回“managers”组的任务:

可以使用任务ID获取特定流程实例的变量,并在屏幕上显示实际的申请:

运行结果如图2.14所示。

图2.14 运行结果

至此,经理可以完成任务了。实际上,这通常是由用户提交一个表单来完成的,表单中的数据作为流程变量传递。这里,我们在完成任务时传递了approved流程变量(这个变量很重要,之后会在顺序流的条件中使用):

现在任务已经完成,根据approved流程变量选择离开独占网关的两条路径之一。

2.3.7 实现JavaDelegate

此时的代码还缺了一块,我们还没有实现申请被批准后执行的自动逻辑。在BPMN 2.0 XML文件中,这是一个服务任务(Service Task):

在现实中,这个逻辑可以做很多事情,比如向某个系统发起一个HTTP REST服务调用,或调用系统中使用了好多年的遗留代码。我们不会在这里实现实际的逻辑,只是简单地记录处理过程。

新建一个Java类CallExternalSystemDelegate,让这个类实现org.flowable.engine.delegate.JavaDelegate接口,并实现execute()方法:

当执行到达服务任务时,系统会实例化并调用BPMN 2.0 XML文件中所引用的类。

现在执行这个实例时,会显示调用外部系统结果的日志信息,说明确实执行了自定义逻辑,如图2.15所示。

图2.15 调用外部系统结果

注意,如果出现“org.flowable.common.engine.api.FlowableException:couldn't instantiate class CallExternalSystemDelegate”的错误信息,则说明包路径未指定正确,在XML文件中,可以根据自己CallExternalSystemDelegate类的实际路径修改:

2.3.8 使用历史数据

Flowable引擎可以自动存储所有流程实例的数据,如果希望显示流程实例执行的时间,可以从ProcessEngine中获取HistoryService服务类,并创建历史活动的查询。在下面的代码片段中可以看到我们添加了一些额外的过滤条件。

(1)指定一个特定流程实例的活动。

(2)只选择已完成的活动。

(3)结果按照结束时间排序,代表我们将按执行顺序获得它们:

再次运行实例,可以看到控制台中显示的信息如下:

最后,需要说明的是,本经典实例来源于官网教程。当学习一个新的技术框架时,不用急于寻找别人的案例教程,可先从官网上学习入门教程,往往官网提供的入门内容更加通俗易懂、易于理解。 vfbKbXno/s0BzHVBrUjSXDSymEeGwPzrJxeonm9VDARgojr6Mtp/GjX3wJc/uiuZ

点击中间区域
呼出菜单
上一章
目录
下一章
×