1.创建ProcessEngine
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
2.流程设计器
Flowable官方给我们提供了一个功能完备的基于web应用的流程设计器。可以用于流程相关的操作。具体提供了如下的功能:
-
Flowable IDM: 身份管理应用。为所有Flowable UI应用提供单点登录认证功能,并且为拥有IDM管理员权限的用户提供了管理用户、组与权限的功能。
-
Flowable Modeler: 让具有建模权限的用户可以创建流程模型、表单、选择表与应用定义。
-
Flowable Task: 运行时任务应用。提供了启动流程实例、编辑任务表单、完成任务,以及查询流程实例与任务的功能。
-
Flowable Admin: 管理应用。让具有管理员权限的用户可以查询BPMN、DMN、Form及Content引擎,并提供了许多选项用于修改流程实例、任务、作业等。管理应用通过REST API连接至引擎,并与Flowable Task应用及Flowable REST应用一同部署。
所有其他的应用都需要Flowable IDM提供认证。每个应用的WAR文件可以部署在相同的servlet容器(如Apache Tomcat)中,也可以部署在不同的容器中。由于每个应用使用相同的cookie进行认证,因此应用需要运行在相同的域名下。
流程部署
我们可以在Spring的环境下部署。也可以在非Spring的环境下部署。下面先展示非Spring环境下的部署操作:
/** * 不通过Spring容器。我们单独的构建ProcessEngine对象来实现部署的操作 */ @Test void contextLoads() { // 1.流程引擎的配置 ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true") .setJdbcUsername("root") .setJdbcPassword("123456") .setJdbcDriver("com.mysql.cj.jdbc.Driver") .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); // 2.构建流程引擎对象 ProcessEngine processEngine = cfg.buildProcessEngine(); System.out.println(processEngine); Deployment deploy = processEngine.getRepositoryService().createDeployment() .addClasspathResource("process/HolidayDemo1.bpmn20.xml") .name("第一个流程案例") .deploy(); System.out.println(deploy.getId()); }
方法执行成功后会在这三张表中记录相关的部署信息
-
act_ge_bytearray:记录流程定义的资源信息。xml和流程图的图片信息
-
act_re_deployment:流程部署表,记录这次的部署行为
-
act_re_procdef:流程定义表,记录这次部署动作对应的流程定义信息
databaseSchemaUpdate:用于设置流程引擎启动关闭时使用的数据库表结构控制策略
-
false
(默认): 当引擎启动时,检查数据库表结构的版本是否匹配库文件版本。版本不匹配时抛出异常。 -
true
: 构建引擎时,检查并在需要时更新表结构。表结构不存在则会创建。 -
create-drop
: 引擎创建时创建表结构,并在引擎关闭时删除表结构。
一次部署操作可以部署多个流程定义
构建流程引擎对象
ProcessEngine processEngine = cfg.buildProcessEngine();
System.out.println(processEngine);
Deployment deploy = processEngine.getRepositoryService().createDeployment()
.addClasspathResource("process/HolidayDemo1.bpmn20.xml") // 部署一个流程
.addClasspathResource("process/消息中间事件.bpmn20.xml") // 部署第二个流程
.name("第一个流程案例")
.deploy();
上面的操作我们是自己定义ProcessEngine
和ProcessEngineConfiguration
来实现流程引擎对象的获取操作,我们完全可以把这些初始化的操作交给Spring容器来管理。
需要在application.yml
中配置 :
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true
username: root
password: 123456
hikari:
minimum-idle: 5
idle-timeout: 600000
maximum-pool-size: 10
auto-commit: true
pool-name: MyHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
flowable:
async-executor-activate: true #关闭定时任务JOB
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。
database-schema-update: true
server:
port: 8082
logging:
level:
org:
flowable: debug
注意在url中需要添加nullCatalogMeansCurrent=true
属性。
具体部署流程的代码,就可以直接从Spring容器中获取ProcessEngine
对象了。大大简化了相关的代码
@Autowired private ProcessEngine processEngine; /** * 流程部署 */ @Test void deployFlow(){ Deployment deploy = processEngine.getRepositoryService().createDeployment() .addClasspathResource("process/HolidayDemo1.bpmn20.xml") // 部署一个流程 .name("第一个流程案例") .deploy(); System.out.println(deploy.getId()); }
3.启动流程实例
/**
* 发起流程
*/
@Test
void startProcess(){
// 发起流程需要通过RuntimeService来实现
RuntimeService runtimeService = processEngine.getRuntimeService();
// act_re_procdef 表中的id
String processId = "HolidayDemo1:1:89fad01e-7a42-11ee-b574-c03c59ad2248";
// 根据流程定义Id启动 返回的是当前启动的流程实例 ProcessInstance
//ProcessInstance processInstance = runtimeService.startProcessInstanceById(processId);
//System.out.println("processInstance.getId() = " + processInstance.getId());
String processKey = "HolidayDemo1";
runtimeService.startProcessInstanceByKey(processKey);
}
启动流程需要通过RuntimeService
来实现。同时在启动流程的时候有两个方法可以调用:
-
startProcessInstanceById: 对应于act_re_procdef 表中的id
-
startProcessInstanceByKey: 对应于act_re_procdef 表中的key
启动流程后根据我们的定义。一步一步往下走。
我们可以在act_ru_task
表中看到对应的记录。act_ru_task
记录的都是当前待办的记录信息
4.流程审批
/**
* 待办任务查询
*/
@Test
void findTask(){
// 任务查询这块我们可以通过 TaskService 来实现
TaskService taskService = processEngine.getTaskService();
// 查询的其实就是 act_ru_task 中的记录
List<Task> list = taskService.createTaskQuery()
.taskAssignee("zhangsan") // 根据审批人来查询
.list();// 返回多条记录
for (Task task : list) {
System.out.println(task.getId());
}
}
/**
* 完成任务的审批
*/
@Test
void completeTask(){
TaskService taskService = processEngine.getTaskService();
// 需要审批的任务 Id
String taskId = "926b41f8-7a4c-11ee-97fd-c03c59ad2248";
taskService.complete(taskId); // 通过complete方法完成审批
}