一、整合

1、依赖

  • Flowable流程引擎。使我们可以创建一个ProcessEngine流程引擎对象,并访问Flowable API。
  1. <properties>
  2. <java.version>1.8</java.version>
  3. <flowable.version>6.7.1</flowable.version>
  4. </properties>
  5. <dependency>
  6. <groupId>org.flowable</groupId>
  7. <artifactId>flowable-spring-boot-starter</artifactId>
  8. <version>6.7.1</version>
  9. </dependency>
  10. <dependency>
  11. <groupId>mysql</groupId>
  12. <artifactId>mysql-connector-java</artifactId>
  13. </dependency>

添加flowable和数据库相关依赖

2、配置文件

mysql连接url添加参数【&nullCatalogMeansCurrent=true】表示在当前schema下生成表

  1. spring:
  2. datasource:
  3. driver-class-name: com.mysql.cj.jdbc.Driver
  4. url: jdbc:mysql://127.0.0.1:3310/flowable6_demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
  5. username: root
  6. password: 123456
  7. # flowable配置
  8. flowable:
  9. database-schema-update: true #创建数据库的规则
  10. async-executor-activate: false #关闭异步
  11. check-process-definitions: true #是否需要自动部署流程定义。默认true
  12. db-history-used: true # 是否要使用db历史。'
  13. history-level: audit # 要使用的历史级别。'
  14. idm:
  15. enabled: false # 是否启用IDM引擎。'
  16. mail:
  17. server:
  18. default-from: zukxu520@163.com # 发送邮件时使用的默认发信人地址。'
  19. host: localhost # 邮件服务器。'
  20. password: # 邮件服务器的登录密码。'
  21. port: 1025 # 邮件服务器的端口号。'
  22. use-ssl: false # 是否使用SSL/TLS加密SMTP传输连接(即SMTPS/POPS)。'
  23. use-tls: false # 使用或禁用STARTTLS加密。'
  24. username: # 邮件服务器的登录用户名。如果为空,则不需要登录。'

第二次的时候可以将该配置设置为false

3、启动项目

创建一个启动类

  1. @SpringBootApplication
  2. public class FlowableApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(FlowableApplication.class, args);
  5. }
  6. }

启动可以发现数据库中创建了Flowable相关的表

首先要做的是初始化ProcessEngine流程引擎实例。这是一个线程安全的对象,
因此通常只需要在一个应用中初始化一次。
ProcessEngineProcessEngineConfiguration实例创建。
该实例可以配置与调整流程引擎的设置。 通常使用一个配置XML文件创建ProcessEngineConfiguration
但是我们也可以编程方式创建它。
ProcessEngineConfiguration所需的最小配置,是数据库JDBC连接:

ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
    .setJdbcUrl("jdbc:mysql://127.0.0.1:3310/flowable6_demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true")
    .setJdbcUsername("root")
    .setJdbcPassword("123456")
    .setJdbcDriver("com.mysql.cj.jdbc.Driver")
    .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

ProcessEngine processEngine = cfg.buildProcessEngine();

第1行创建了一个独立(standalone)配置对象。
这里的‘独立’指的是引擎是完全独立创建及使用的(而不是在Spring环境中使用,这时需要使用SpringProcessEngineConfiguration类代替)。
第2至5行中,传递了一个mysql数据库实例的JDBC连接参数。
第6行中,设置了true,确保在JDBC参数连接的数据库中,数据库表结构不存在时,会创建相应的表结构。 另外,Flowable也提供了一组SQL文件,可用于手动创建所有表的数据库表结构。

然后使用这个配置创建ProcessEngine对象(第8行)。

4、日志

flowable 使用slf4j作为日志框架,我们可以使用log4j作为其日志实现框架

    <!--日志依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.0-alpha6</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>2.0.0-alpha6</version>
            <scope>test</scope>
        </dependency>

Log4j需要一个配置文件。在src/main/resources文件夹下添加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

二、流程定义

1、定义

Flowable引擎需要流程定义为BPMN 2.0格式,这是一个业界广泛接受的XML标准
这样的一个xml文件我们就称之为一个流程定义
一个流程定义部署后可以启动多个流程实例

一般来说,流程定义使用可视化建模工具建立,
如IDEA插件【Flowable BPMN visualizer】或Web应用【Flowable Web Modeler】。
或者前端Web组件:https://www.yuque.com/docs/share/6fba0ef2-ccf1-40a6-a4e7-4029920e1367?# 《bpmn前端组件》

可以将生成的【.bpmn20.xml】文件保存在src/main/resources文件夹下名为
【flowable】的文件夹中。

  • 每一个步骤(在BPMN 2.0术语中称作活动(activity))都有一个id属性,

为其提供一个在XML文件中唯一的标识符。所有的活动都可以设置一个名字,以提高流程图的可读性。

  • 活动之间通过顺序流(sequence flow)连接,在流程图中是一个有向箭头。在执行流程实例时,执行(execution)会从启动事件沿着顺序流流向下一个活动。
  • 离开排他网关(带有X的菱形)的顺序流很特别:都以表达式(expression)的形式定义了条件(condition) 当流程实例的执行到达这个网关时,会计算条件,并使用第一个计算为true的顺序流。这就是排他的含义:只选择一个。当然如果需要不同的路由策略,可以使用其他类型的网关。
  • 用作条件的表达式为${approved},这是${approved == true}的简写。变量‘approved’被称作流程变量(process variable)。流程变量是持久化的数据,与流程实例存储在一起,并可以在流程实例的生命周期中使用。

2、部署

部署一个流程定义意味着:

  • 流程引擎会将XML文件存储在数据库中,这样可以在需要的时候获取它。
  • 流程定义转换为内部的、可执行的对象模型,这样使用它就可以启动流程实例

将流程定义部署至Flowable引擎,需要使用RepositoryService
其可以从ProcessEngine对象获取。使用RepositoryService,可以通过XML文件的路径创建一个新的部署(Deployment),并调用deploy()方法实际执行:

 /**
     * 部署流程定义
     *
     * @return
     */
    public R<?> deployDefinition() {

        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("flowable/holiday-request.bpmn20.xml")
                .deploy();
        return R.ok(deployment);
    }

3、流程实例

如果我们的流程定义在设计之初有流程变量存在,
那么如果我们要启动流程实例,就需要将所有的流程变量都初始化,否则会抛出异常无法启动流程实例
一般来说,流程变量都可以通过呈现给用户的表单,或者在流程由其他系统自动触发时通过REST API,来设置或者获取这些变量

我们使用RuntimeService启动一个流程实例。
收集的数据作为一个java.util.Map实例传递作为流程变量
其中的键就是之后用于获取变量的标识符。
在本案例中的流程变量就是:
employee
nrOfHolidays
description
这个流程实例使用key启动。这个key就是BPMN 2.0 XML文件中设置的id属性,
在这个例子里key就是【holidayRequest】。

  /**
     * 根据流程定义id启动流程实例
     *
     * @param procDefId 流程定义id
     * @param variables 流程变量
     * @return R
     */
    public R<?> addNewInstanceById(String procDefId, Map<String, Object> variables) {
        try {
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
            RMap rMap = new RMap().put("processInstanceId", processInstance.getProcessInstanceId());
            return R.ok(rMap).message("流程启动成功");
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("流程启动错误");
        }
    }

    /**
     * 根据流程定义id启动流程实例
     *
     * @param procDefKey 流程定义Key
     * @param variables  流程变量
     * @return R
     */
    public R<?> addNewInstanceByKey(String procDefKey, Map<String, Object> variables) {
        try {
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(procDefKey, variables);
            RMap rMap = new RMap().put("processInstanceId", processInstance.getProcessInstanceId());
            return R.ok(rMap).message("流程启动成功");
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("流程启动错误");
        }
    }

在流程实例启动后,会创建一个执行(execution),并将其放在启动事件上。从这里开始,这个执行沿着顺序流移动到经理审批的用户任务,并执行用户任务行为。这个行为将在数据库中创建一个任务,该任务可以之后使用查询找到。用户任务是一个等待状态(wait state)

三、历史数据

flowable可以自动存储所有流程实例的审计数据历史数据。这些数据可以用于创建报告,深入展现组织运行的情况,瓶颈在哪里,等等。

附录:

https://tkjohn.github.io/flowable-userguide/#restApiChapter

配置相关


# Core (Process) FlowableProperties
# 核心(流程)
flowable.check-process-definitions=true # 是否需要自动部署流程定义。
flowable.custom-mybatis-mappers= # 需要添加至引擎的自定义Mybatis映射的FQN。
flowable.custom-mybatis-x-m-l-mappers= # 需要添加至引擎的自定义Mybatis XML映射的路径。
flowable.database-schema= # 如果数据库返回的元数据不正确,可以在这里设置schema用于检测/生成表。
flowable.database-schema-update=true # 数据库schema更新策略。
flowable.db-history-used=true # 是否要使用db历史。
flowable.deployment-name=SpringBootAutoDeployment # 自动部署的名称。
flowable.history-level= # 要使用的历史级别。
flowable.process-definition-location-prefix=classpath*:/processes/ # 自动部署时查找流程的目录。
flowable.process-definition-location-suffixes=**.bpmn20.xml,**.bpmn # 'processDefinitionLocationPrefix'路径下需要部署的文件的后缀(扩展名)。

# Process FlowableProcessProperties
# 流程
flowable.process.definition-cache-limit=-1 # 流程定义缓存中保存流程定义的最大数量。默认值为-1(缓存所有流程定义)。
flowable.process.enable-safe-xml=true # 在解析BPMN XML文件时进行额外检查。参见 https://www.flowable.org/docs/userguide/index.html#advanced.safe.bpmn.xml 。不幸的是,部分平台(JDK 6,JBoss)上无法使用这个功能,因此如果你所用的平台在XML解析时不支持StaxSource,需要禁用这个功能。
flowable.process.servlet.load-on-startup=-1 # 启动时加载Process servlet。
flowable.process.servlet.name=Flowable BPMN Rest API # Process servlet的名字。
flowable.process.servlet.path=/process-api # Process servelet的context path。

# Process Async Executor
# 流程异步执行器
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 # 异步作业获取线程在进行下次获取查询前的等待时间(以毫秒计)。只在当次没有取到新的异步作业,或者只取到很少的异步作业时生效。默认值 = 10秒。
flowable.process.async.executor.default-queue-size-full-wait-time-in-millis=0 # 异步作业(包括定时器作业与异步执行)获取线程在队列满时,等待执行下次查询的等待时间(以毫秒计)。默认值为0(以向后兼容)
flowable.process.async.executor.default-timer-job-acquire-wait-time-in-millis=10000 # 定时器作业获取线程在进行下次获取查询前的等待时间(以毫秒计)。只在当次没有取到新的定时器作业,或者只取到很少的定时器作业时生效。默认值 = 10秒。
flowable.process.async.executor.max-async-jobs-due-per-acquisition=1 # (译者补)单次查询的异步作业数量。默认值为1,以降低乐观锁异常的可能性。除非你知道自己在做什么,否则请不要修改这个值。
flowable.process.async.executor.retry-wait-time-in-millis=500 # ???(译者补不了了)
flowable.process.async.executor.timer-lock-time-in-millis=300000 # 定时器作业在被异步执行器取走后的锁定时间(以毫秒计)。在这段时间内,其它异步执行器不会尝试获取及锁定这个任务。


# CMMN FlowableCmmnProperties
flowable.cmmn.deploy-resources=true # 是否部署资源。默认值为'true'。
flowable.cmmn.deployment-name=SpringBootAutoDeployment # CMMN资源部署的名字。
flowable.cmmn.enable-safe-xml=true # 在解析CMMN XML文件时进行额外检查。参见 https://www.flowable.org/docs/userguide/index.html#advanced.safe.bpmn.xml 。不幸的是,部分平台(JDK 6,JBoss)上无法使用这个功能,因此如果你所用的平台在XML解析时不支持StaxSource,需要禁用这个功能。
flowable.cmmn.enabled=true # 是否启用CMMN引擎。
flowable.cmmn.resource-location=classpath*:/cases/ # CMMN资源的路径。
flowable.cmmn.resource-suffixes=**.cmmn,**.cmmn11,**.cmmn.xml,**.cmmn11.xml # 需要扫描的资源后缀名。
flowable.cmmn.servlet.load-on-startup=-1 # 启动时加载CMMN servlet。
flowable.cmmn.servlet.name=Flowable CMMN Rest API # CMMN servlet的名字。
flowable.cmmn.servlet.path=/cmmn-api # CMMN servlet的context path。

# CMMN Async Executor
# CMMN异步执行器
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 # 异步作业获取线程在进行下次获取查询前的等待时间(以毫秒计)。只在当次没有取到新的异步作业,或者只取到很少的异步作业时生效。默认值 = 10秒。
flowable.cmmn.async.executor.default-queue-size-full-wait-time-in-millis=0 # 异步作业(包括定时器作业与异步执行)获取线程在队列满时,等待执行下次查询的等待时间(以毫秒计)。默认值为0(以向后兼容)
flowable.cmmn.async.executor.default-timer-job-acquire-wait-time-in-millis=1000 # 定时器作业获取线程在进行下次获取查询前的等待时间(以毫秒计)。只在当次没有取到新的定时器作业,或者只取到很少的定时器作业时生效。默认值 = 10秒。
flowable.cmmn.async.executor.max-async-jobs-due-per-acquisition=1 # (译者补)单次查询的异步作业数量。默认值为1,以降低乐观锁异常的可能性。除非你知道自己在做什么,否则请不要修改这个值。
flowable.cmmn.async.executor.retry-wait-time-in-millis=500 #(译者补不了了)
flowable.cmmn.async.executor.timer-lock-time-in-millis=300000 # 定时器作业在被异步执行器取走后的锁定时间(以毫秒计)。在这段时间内,其它异步执行器不会尝试获取及锁定这个任务。

# Content FlowableContentProperties
flowable.content.enabled=true # 是否启动Content引擎。
flowable.content.servlet.load-on-startup=-1 # 启动时加载Content servlet。
flowable.content.servlet.name=Flowable Content Rest API # Content servlet的名字。
flowable.content.servlet.path=/content-api # Content servlet的context path。
flowable.content.storage.create-root=true # 如果根路径不存在,是否需要创建?
flowable.content.storage.root-folder= # 存储content文件(如上传的任务附件,或表单文件)的根路径。

# DMN FlowableDmnProperties
flowable.dmn.deploy-resources=true # 是否部署资源。默认为'true'。
flowable.dmn.deployment-name=SpringBootAutoDeployment # DMN资源部署的名字。
flowable.dmn.enable-safe-xml=true # 在解析DMN XML文件时进行额外检查。参见 https://www.flowable.org/docs/userguide/index.html#advanced.safe.bpmn.xml 。不幸的是,部分平台(JDK 6,JBoss)上无法使用这个功能,因此如果你所用的平台在XML解析时不支持StaxSource,需要禁用这个功能。
flowable.dmn.enabled=true # 是否启用DMN引擎。
flowable.dmn.history-enabled=true # 是否启用DMN引擎的历史。
flowable.dmn.resource-location=classpath*:/dmn/ # DMN资源的路径。
flowable.dmn.resource-suffixes=**.dmn,**.dmn.xml,**.dmn11,**.dmn11.xml # 需要扫描的资源后缀名。
flowable.dmn.servlet.load-on-startup=-1 # 启动时加载DMN servlet。
flowable.dmn.servlet.name=Flowable DMN Rest API # DMN servlet的名字。
flowable.dmn.servlet.path=/dmn-api # DMN servlet的context path。
flowable.dmn.strict-mode=true # 如果希望避免抉择表命中策略检查导致失败,可以将本参数设置为false。如果检查发现了错误,会直接返回错误前一刻的中间结果。

# Form FlowableFormProperties
flowable.form.deploy-resources=true # 是否部署资源。默认为'true'。
flowable.form.deployment-name=SpringBootAutoDeployment # Form资源部署的名字。
flowable.form.enabled=true # 是否启用Form引擎。
flowable.form.resource-location=classpath*:/forms/ # Form资源的路径。
flowable.form.resource-suffixes=**.form # 需要扫描的资源后缀名。
flowable.form.servlet.load-on-startup=-1 # 启动时加载Form servlet。
flowable.form.servlet.name=Flowable Form Rest API # Form servlet的名字。
flowable.form.servlet.path=/form-api # Form servlet的context path。

# IDM FlowableIdmProperties
flowable.idm.enabled=true # 是否启用IDM引擎。
flowable.idm.password-encoder= # 使用的密码编码类型。
flowable.idm.servlet.load-on-startup=-1 # 启动时加载IDM servlet。
flowable.idm.servlet.name=Flowable IDM Rest API # IDM servlet的名字。
flowable.idm.servlet.path=/idm-api # IDM servlet的context path。

# IDM Ldap FlowableLdapProperties
flowable.idm.ldap.attribute.email= # 用户email的属性名。
flowable.idm.ldap.attribute.first-name= # 用户名字的属性名。
flowable.idm.ldap.attribute.group-id= # 用户组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= # 用户ID的属性名。
flowable.idm.ldap.base-dn= # 查找用户与组的DN(标志名称 distinguished name)。
flowable.idm.ldap.cache.group-size=-1 # 设置{@link org.flowable.ldap.LDAPGroupCache}的大小。这是LRU缓存,用于缓存用户及组,以避免每次都查询LDAP系统。
flowable.idm.ldap.custom-connection-parameters= # 用于设置所有没有专用setter的LDAP连接参数。查看 http://docs.oracle.com/javase/tutorial/jndi/ldap/jndi.html 介绍的自定义参数。参数包括配置链接池,安全设置,等等。
flowable.idm.ldap.enabled=false # 是否启用LDAP IDM 服务。
flowable.idm.ldap.group-base-dn= # 组查找的DN。
flowable.idm.ldap.initial-context-factory=com.sun.jndi.ldap.LdapCtxFactory # 初始化上下文工厂的类名。
flowable.idm.ldap.password= # 连接LDAP系统的密码。
flowable.idm.ldap.port=-1 # LDAP系统的端口。
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= # 按照userId查找用户所用的语句。
flowable.idm.ldap.search-time-limit=0 # 查询LDAP的超时时间(以毫秒计)。默认值为'0',即“一直等待”。
flowable.idm.ldap.security-authentication=simple # 连接LDAP系统所用的'java.naming.security.authentication'参数的值。
flowable.idm.ldap.server= # LDAP系统的主机名。如'ldap://localhost'。
flowable.idm.ldap.user= # 连接LDAP系统的用户ID。
flowable.idm.ldap.user-base-dn= # 查找用户的DN。

# Flowable Mail FlowableMailProperties
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 # 是否使用SSL/TLS加密SMTP传输连接(即SMTPS/POPS)。
flowable.mail.server.use-tls=false # 使用或禁用STARTTLS加密。
flowable.mail.server.username= # 邮件服务器的登录用户名。如果为空,则不需要登录。

# Actuator
management.endpoint.flowable.cache.time-to-live=0ms # 缓存响应的最大时间。
management.endpoint.flowable.enabled=true # 是否启用flowable端点。