Flowable是一个用java语言编写的轻量级业务流程引擎。它允许部署遵守BPMN 2.0(一种工业的流程定义XML标准)规范的流程定义。通过流程定义,可以创建流程实例,通过流程实例可以执行查询、历史数据查询和相关流程数据查看等。文章下面会循序渐进介绍一些相关概念,并通过API展示让你慢慢熟悉,达到最终可以很好使用。 Flowable在构建项目的时候非常灵活,你可以再项目中把JAR包作为依赖使用它,也可以把它单独作为一个应用使用。
2.1.2 Flowable 和 ActivitiFlowable是Activiti(Alfresco的注册商标)的一个分支。在以下所有部分中,您将注意到包名、配置文件等都使用flowable。
2.1.3 构建命令行应用程序 2.1.3.1 创建一个流程引擎使用开发工具idea构建一个简单的maven项目,创建项目流程如下:
选择 New -> Module
填写ArtifactId,这里填写的是flowable-holiday,名称填写完成以后点击右下角的Next按钮
进到下面的界面,点击Finish完成项目创建
到此我们创建成功了一个Maven的Module项目,项目的整体结构如下:
打开新建Module中的pom.xml在里面加上如下依赖:
flowable-engine h2 |
选中pom.xml点击鼠标右键,选中Maven-> Reimport,重新加载一下pom文件,下载所需要的依赖。
在新建Module下面新建一个HolidayRequest.java的文件:
package com.dream21th.flowable;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
public class HolidayRequest {
public static void main(String[] args) {
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
.setJdbcUsername("sa")
.setJdbcPassword("")
.setJdbcDriver("org.h2.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
}
}
运行上面代码,控制台输出如下内容:
从上面控制台输出的内容来看,也没有什么有用的信息,我们可以增加一些日志的输出,在pom.xml文件中新增下面依赖:
org.slf4j slf4j-api1.7.30 org.slf4j slf4j-log4j121.7.30
在src/main/resources目录下面新建文件log4j.properties。重新运行上面的main方法,控制台输出如下内容:
到此,我们创建一个简单的流程引擎。
2.1.3.2 部署一个流程定义下面我们部署一个简单的请假的流程定义,流程定义文件是一个标准的XML文件,他们遵循BPMN 2.0规范。下面是本次部署流程定义的流程图:
下图对上面流程定义中的图标做了一些说明,具体含义建下图:
在src/main/resources下面创建一个holiday-request.bpmn20.xml文件,文件内容如下:
在上面的HolidayRequest.java增加代码后的整体代码如下:
package com.dream21th.flowable;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
public class HolidayRequest {
public static void main(String[] args) {
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
.setJdbcUsername("sa")
.setJdbcPassword("")
.setJdbcDriver("org.h2.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("holiday-request.bpmn20.xml")
.deploy();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.singleResult();
System.out.println("Found process definition : " + processDefinition.getName());
}
}
2.1.3.3 启动一个流程实例
上面我们部署了一个流程定义,流程定义的key是holidayRequest,下面我们可以通过流程定义的key来开启一个流程实例。在main方法中新增下面代码,主要是控制在键盘上输入一些参数。
Scanner scanner= new Scanner(System.in);
System.out.println("Who are you?");
String employee = scanner.nextLine();
System.out.println("How many holidays do you want to request?");
Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());
System.out.println("Why do you need them?");
String description = scanner.nextLine();
通过下面代码要开启一个流程实例
RuntimeService runtimeService = processEngine.getRuntimeService(); Mapvariables = new HashMap (); variables.put("employee", employee); variables.put("nrOfHolidays", nrOfHolidays); variables.put("description", description); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables); System.out.println(processInstance.getId());
添加代码后的main方法的整体内容如下:
package com.dream21th.flowable;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class HolidayRequest {
public static void main(String[] args) {
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
.setJdbcUsername("sa")
.setJdbcPassword("")
.setJdbcDriver("org.h2.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("holiday-request.bpmn20.xml")
.deploy();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.singleResult();
System.out.println("Found process definition : " + processDefinition.getName());
Scanner scanner= new Scanner(System.in);
System.out.println("Who are you?");
String employee = scanner.nextLine();
System.out.println("How many holidays do you want to request?");
Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());
System.out.println("Why do you need them?");
String description = scanner.nextLine();
RuntimeService runtimeService = processEngine.getRuntimeService();
Map variables = new HashMap();
variables.put("employee", employee);
variables.put("nrOfHolidays", nrOfHolidays);
variables.put("description", description);
ProcessInstance processInstance =
runtimeService.startProcessInstanceByKey("holidayRequest", variables);
System.out.println(processInstance.getId());
}
2.1.3.4 查询和完成一个任务
修改holiday-request.bpmn20.xml流程定义文件,修改后的内容如下:
在HolidayRequest.java代码中增加下面代码:
TaskService taskService = processEngine.getTaskService(); //查询候选组是managers的任务 Listtasks = taskService.createTaskQuery().taskCandidateGroup("managers").list(); System.out.println("You have " + tasks.size() + " tasks:"); for (int i=0; i System.out.println("Which task would you like to complete?"); int taskIndex = Integer.valueOf(scanner.nextLine()); Task task = tasks.get(taskIndex - 1); //查询任务的过程变量 MapprocessVariables = taskService.getVariables(task.getId()); System.out.println(processVariables.get("employee") + " wants " + processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?"); boolean approved = scanner.nextLine().toLowerCase().equals("y"); variables = new HashMap(); variables.put("approved", approved); //完成任务 taskService.complete(task.getId(), variables); 执行控制台输出如下:
2.1.3.5 写一个JavaDelegate在自动任务中,通常需要写一个代理类,主要如:
代理类的内容如下:
package com.dream21th.flowable; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.JavaDelegate; public class CallExternalSystemDelegate implements JavaDelegate { public void execute(DelegateExecution delegateExecution) { System.out.println("Calling the external system for employee " + delegateExecution.getVariable("employee")); } }执行的结果如下:
2.1.3.6 查询历史数据流程实例执行中或者执行完成,我们可以通过下面的代码查询历史数据
HistoryService historyService = processEngine.getHistoryService(); Listactivities = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstance.getId()) .finished() .orderByHistoricActivityInstanceEndTime().asc() .list(); for (HistoricActivityInstance activity : activities) { System.out.println(activity.getActivityId() + " took " + activity.getDurationInMillis() + " milliseconds"); } 整体代码如下:
package com.dream21th.flowable; import org.flowable.engine.*; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration; 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 java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; public class HolidayRequest { public static void main(String[] args) { ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1") .setJdbcUsername("sa") .setJdbcPassword("") .setJdbcDriver("org.h2.Driver") .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); ProcessEngine processEngine = cfg.buildProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); Deployment deployment = repositoryService.createDeployment() .addClasspathResource("holiday-request.bpmn20.xml") .deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deployment.getId()) .singleResult(); System.out.println("Found process definition : " + processDefinition.getName()); Scanner scanner= new Scanner(System.in); System.out.println("Who are you?"); String employee = scanner.nextLine(); System.out.println("How many holidays do you want to request?"); Integer nrOfHolidays = Integer.valueOf(scanner.nextLine()); System.out.println("Why do you need them?"); String description = scanner.nextLine(); RuntimeService runtimeService = processEngine.getRuntimeService(); Mapvariables = new HashMap (); variables.put("employee", employee); variables.put("nrOfHolidays", nrOfHolidays); variables.put("description", description); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables); System.out.println(processInstance.getId()); TaskService taskService = processEngine.getTaskService(); //查询候选组是managers的任务 List tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list(); System.out.println("You have " + tasks.size() + " tasks:"); for (int i=0; i processVariables = taskService.getVariables(task.getId()); System.out.println(processVariables.get("employee") + " wants " + processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?"); boolean approved = scanner.nextLine().toLowerCase().equals("y"); variables = new HashMap (); variables.put("approved", approved); //完成任务 taskService.complete(task.getId(), variables); HistoryService historyService = processEngine.getHistoryService(); List activities = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstance.getId()) .finished() .orderByHistoricActivityInstanceEndTime().asc() .list(); for (HistoricActivityInstance activity : activities) { System.out.println(activity.getActivityId() + " took " + activity.getDurationInMillis() + " milliseconds"); } } } 执行结果



