1、表结构讲解
Flowable的所有数据库表都以**ACT_**开头。第二部分是说明表用途的两字符标示符。服务API的命名也大略符合这个规则。
- ACT_RE_*: 'RE’代表
repository
。带有这个前缀的表包含“静态”信息,例如流程定义与流程资源(图片、规则等)。 - ACT_RU_*: 'RU’代表
runtime
。这些表存储运行时信息,例如流程实例(process instance)、用户任务(user task)、变量(variable)、作业(job)等。Flowable只在流程实例运行中保存运行时数据,并在流程实例结束时删除记录。这样保证运行时表小和快。 - ACT_HI_*: 'HI’代表
history
。这些表存储历史数据,例如已完成的流程实例、变量、任务等。 - ACT_GE_*: GE 表示 general,通用数据。在多处使用。
- ACT_ID_*: GE 表示 identity(组织机构),这些表包含标识的信息,如用户,用户组等等。
1)通用数据表(2个)
act_ge_bytearray:二进制数据表,如流程定义、流程模板、流程图的字节流文件;
act_ge_property:属性数据表(不常用);
2)历史表(8个,HistoryService接口操作的表)
act_hi_actinst:历史节点表,存放流程实例运转的各个节点信息(包含开始、结束等非任务节点);
act_hi_attachment:历史附件表,存放历史节点上传的附件信息(不常用);
act_hi_comment:历史意见表;
act_hi_detail:历史详情表,存储节点运转的一些信息(不常用);
act_hi_identitylink:历史流程人员表,存储流程各节点候选、办理人员信息,常用于查询某人或部门的已办任务;
act_hi_procinst:历史流程实例表,存储流程实例历史数据(包含正在运行的流程实例);
act_hi_taskinst:历史流程任务表,存储历史任务节点;
act_hi_varinst:流程历史变量表,存储流程历史节点的变量信息;
3)用户相关表(4个,IdentityService接口操作的表)
act_id_group:用户组信息表,对应节点选定候选组信息;
act_id_info:用户扩展信息表,存储用户扩展信息;
act_id_membership:用户与用户组关系表;
act_id_user:用户信息表,对应节点选定办理人或候选人信息;
4)流程定义、流程模板相关表(3个,RepositoryService接口操作的表)
act_re_deployment:部属信息表,存储流程定义、模板部署信息;
act_re_procdef:流程定义信息表,存储流程定义相关描述信息,但其真正内容存储在act_ge_bytearray表中,以字节形式存储;
act_re_model:流程模板信息表,存储流程模板相关描述信息,但其真正内容存储在act_ge_bytearray表中,以字节形式存储;
5)流程运行时表(6个,RuntimeService接口操作的表)
act_ru_task:运行时流程任务节点表,存储运行中流程的任务节点信息,重要,常用于查询人员或部门的待办任务时使用;
act_ru_event_subscr:监听信息表,不常用;
act_ru_execution:运行时流程执行实例表,记录运行中流程运行的各个分支信息(当没有子流程时,其数据与act_ru_task表数据是一一对应的);
act_ru_identitylink:运行时流程人员表,重要,常用于查询人员或部门的待办任务时使用;
act_ru_job:运行时定时任务数据表,存储流程的定时任务信息;
act_ru_variable:运行时流程变量数据表,存储运行中的流程各节点的变量信息;
2、ProcessEngine讲解
硬编码的方式
@Test
public void TestProcessEngine() {
// 创建ProcessEngineConfiguration实例,该实例可以配置与调整流程引擎的设置
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:mysql://192.168.27.111:3306/flowable_learn?serverTimezone=UTC&nullCatalogMeansCurrent=true&useSSL=false")
.setJdbcUsername("root")
.setJdbcPassword("123456")
.setJdbcDriver("com.mysql.jdbc.Driver")
// 如果数据库中的表结构不存在就新建
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 获取ProcessEngine对象
ProcessEngine processEngine = cfg.buildProcessEngine();
System.out.println("processEngine==" + processEngine);
}
默认配置文件方式
Flowable流程引擎通过名为flowable.cfg.xml
的XML文件进行配置。
/**
* 加载默认的配置文件
* flowable.cfg.xml
*/
@Test
public void TestProcessEngine2() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println("processEngine==" + defaultProcessEngine);
}
这样会从classpath寻找flowable.cfg.xml
,并用这个文件中的配置构造引擎。下面的代码展示了一个配置的例子。
flowable.cfg.xml
文件中必须包含一个id为’processEngineConfiguration’的bean。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:mysql://192.168.27.111:3306/flowable_learn?serverTimezone=UTC&nullCatalogMeansCurrent=true&useSSL=false" />
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="123456" />
<property name="databaseSchemaUpdate" value="true" />
<property name="asyncExecutorActivate" value="false" />
</bean>
</beans>
(这里可以查看getDefaultProcessEngine方法,可以发现默认的配置文件是flowable.cfg.xml
)
自定义配置文件方式
所有的ProcessEngineConfiguration.createXXX()
方法都返回ProcessEngineConfiguration
,并可以继续按需调整。调用buildProcessEngine()
后,生成一个ProcessEngine
/**
* 加载自定义名称的配置文件
*/
@Test
public void TestProcessEngine3() {
ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("flowable.cfg.xml");
ProcessEngine processEngine = cfg.buildProcessEngine();
System.out.println("processEngine==" + processEngine);
}
3、流程引擎API与服务
引擎API是与Flowable交互的最常用手段。总入口点是ProcessEngine
。ProcessEngine可以使用多种方式创建。使用ProcessEngine,可以获得各种提供工作流/BPM方法的服务。ProcessEngine与服务对象都是线程安全的,因此可以在服务器中保存并共用同一个引用。
Service的创建方式
通过ProcessEngine创建Service。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
在ProcessEngines.getDefaultProcessEngine()
第一次被调用时,将初始化并构建流程引擎,之后的重复调用都会返回同一个流程引擎。可以通过ProcessEngines.init()
创建流程引擎,并由ProcessEngines.destroy()
关闭流程引擎。
ProcessEngines会扫描flowable.cfg.xml
与flowable-context.xml
文件。对于flowable.cfg.xml
文件,流程引擎会以标准Flowable方式构建引擎:ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()
。对于flowable-context.xml
文件,流程引擎会以Spring的方式构建:首先构建Spring应用上下文,然后从该上下文中获取流程引擎。
所有的服务都是无状态的。这意味着你可以很容易的在集群环境的多个节点上运行Flowable,使用同一个数据库,而不用担心上一次调用实际在哪台机器上执行。不论在哪个节点执行,对任何服务的任何调用都是幂等(idempotent)的。
Service总览
RepositoryService
很可能是使用Flowable引擎要用的第一个服务。这个服务提供了管理与控制部署(deployments)与流程定义(process definitions)的操作。管理静态信息。
此外,这个服务还可以:
- 查询引擎现有的部署与流程定义。
- 暂停或激活部署中的某些流程,或整个部署。暂停意味着不能再对它进行操作,激活刚好相反,重新使它可以操作。
- 获取各种资源,比如部署中保存的文件,或者引擎自动生成的流程图。
- 获取POJO版本的流程定义。它可以用Java而不是XML的方式查看流程。
RuntimeService
用于启动流程定义的新流程实例。
RuntimeService
也用于读取与存储流程变量
。
RuntimeService
还可以用于查询流程实例与执行(Execution)。
还可以在流程实例等待外部触发时使用RuntimeService
,使流程可以继续运行。RuntimeService
服务提供了许多操作用于“通知”流程实例:已经接收到外部触发,流程实例可以继续运行。
TaskService
- 查询分派给用户或组的任务
- 创建*独立运行(standalone)*任务。这是一种没有关联到流程实例的任务。
- 决定任务的执行用户(assignee),或者将用户通过某种方式与任务关联。
- 认领(claim)与完成(complete)任务。认领是指某人决定成为任务的执行用户,也即他将会完成这个任务。完成任务是指“做这个任务要求的工作”,通常是填写某个表单。
IdentityService
很简单。它用于管理(创建,更新,删除,查询……)组与用户。
HistoryService
暴露Flowable引擎收集的所有历史数据。当执行流程时,引擎会保存许多数据(可配置),例如流程实例启动时间、谁在执行哪个任务、完成任务花费的事件、每个流程实例的执行路径,等等。这个服务主要提供查询这些数据的能力。
FormService
是可选服务。也就是说Flowable没有它也能很好地运行,而不必牺牲任何功能。
ManagementService
通常在用Flowable编写用户应用时不需要使用。它可以读取数据库表与表原始数据的信息,也提供了对作业(job)的查询与管理操作。
引擎管理类,揭供了对Fwable 流程引率的管理和维护功能,这些功能不在工作流动的应用程序中便用,主要用于 Flwable 系统的日常推护。
DynamicBpmnService
可用于修改流程定义中的部分内容,而不需要重新部署它。例如可以修改流程定义中一个用户任务的办理人设置,或者修改一个服务任务中的类名。
4、图标介绍
BPMN (Business Process Model AndNotation)-业务流程模型和符号是由BPMI (BusinessProcessManagement Initiative)开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。
2004年5月发布了BPMN1.0规范。BPMI于2005年9月并入OMG (The Object Management Group对象管理组织)组织。OMG于2011年1月发布BPMN2.0的最终版本。
BPMN是目前被各BPM厂商广泛接受的BPM标准。Activiti就是使用BPMN 2.0进行流程建模、流程执行管理,它包括很多的建模符号。
官方解释如下:
标准的业务流程模型和符号 (BPMN) 将为企业提供以图形符号理解其内部业务程序的能力,并使组织能够以标准方式交流这些程序。此外,图形符号将有助于理解组织之间的绩效协作和业务交易。这将确保企业了解自身和业务参与者,并使组织能够快速适应新的内部和 B2B 业务环境。
事件图标
Flowable中的事件图标分为 启动事件,边界事件,中间事件和结束事件
任务(任务)图标
活动是工作或任务的一个诞用术语。一个活动可以是一个任务,还可以是一个当前流程的子处理流程,其次,你还可以为活动指定不同的类型,常见活动有:
结构图标
整个流程活动的结构,一个流程中可以包括子流程。
网关图标
网关是用来处理决策的。
5、流程部署详解
部署实现
@Test
public void TestDeployment() {
// 获取ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
// .bar文件(eclipse产生的bar文件) 或者 zip文件
InputStream is = this.getClass().getClassLoader().getResourceAsStream("myHoliday.bar");
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(new ZipInputStream(is))
.name("XXX公司请假流程")
.deploy();
System.out.println("deployment.getId()" + deployment.getId());// 1
System.out.println("deployment.getName()" + deployment.getName());
}
涉及的表:
act_re_deployment,流程部署表,一次流程部署操作就会产生一条记录
act_re_procdef ,流程定义表,一次部署操作中包含几个流程定义文件就会产生几条记录
act_ge_bytearray,流程定义资源文件表,有多少资源就会产生几条记录
act_re_procdef 表和act_re_deployment 是多对一的关系,即,一个部署bar里可能包含多流程定义文件,每个流程定义文件都会有一条记录在act_re_procdef 表内,
每个流程定义的数据,都会对应act_ge_bytearray 表内的一个资源文件和PNG图片文件,和act_ge_bytearray 的关联是通过程序用act_ge_bytearray.name 与 act_re_procdef.name完成的。
挂起和激活
部署的流程默认的状态为激活,如果我们暂时不想使用该定义的流程,那么可以挂起该流程,当然该流程定义下边所有的流程实例全部暂停。
流程定义为挂起状态,该流程定义将不允许启动新的流程实例,同时该流程定义下的所有的流程实例都将全部挂起暂停执行。
@Test
public void TestSuspended() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
// 获取对应的流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionId("holidayRequest:1:10003")
.singleResult();
// 状态信息
boolean suspended = processDefinition.isSuspended();
if(suspended){
// 当前的流程挂起了,可以激活流程
System.out.println("激活流程:" + processDefinition.getId() + "===" + processDefinition.getName());
repositoryService.activateProcessDefinitionById("holidayRequest:1:10003");
}else {
// 当前的流程是激活状态,可以挂起流程
System.out.println("挂起流程:" + processDefinition.getId() + "===" + processDefinition.getName());
repositoryService.suspendProcessDefinitionByKey("holidayRequest");
}
}
6、启动流程实例
启动流程实例代码
@Test
public void TestDeploymentRun() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 流程变量
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employee", "张三");
variables.put("nrOfHolidays", 3);
variables.put("description", "有事需请假");
// 启动流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceById("holidayRequest:1:10003", variables);
System.out.println("processInstance.getProcessDefinitionId() = " + processInstance.getProcessDefinitionId());
System.out.println("processInstance.getActivityId() = " + processInstance.getActivityId());
System.out.println("processInstance.getId()" + processInstance.getId());
}
结果:
processInstance.getProcessDefinitionId() = holidayRequest:1:10003
processInstance.getActivityId() = null
processInstance.getId()17501
启动一个流程实例的时候涉及到的表有:
act_ru_execution:运行时流程执行实例表,记录运行中流程运行的各个分支信息(当没有子流程时,其数据与act_ru_task表数据是一一对应的);
act_ru_identitylink:运行时流程人员表,重要,常用于查询人员或部门的待办任务时使用;
act_ru_task:运行时流程任务节点表,存储运行中流程的任务节点信息,重要,常用于查询人员或部门的待办任务时使用
act_ru_variable:运行时流程变量数据表,存储运行中的流程各节点的变量信息;
说明字段:
act_ru_identitylink的TYPE_:assignee支配人(组)、candidate候选人(组)、owner拥有人、participant参与者
7、处理流程
@Test
public void TestCompleteTask() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery()
.processInstanceId("22501") //根据流程实例编号查找
.taskCandidateGroup("managers")
.singleResult();
// 获取当前流程绑定的流程变量
Map<String, Object> processVariables = taskService.getVariables(task.getId());
Set<String> keySet = processVariables.keySet();
for (String key : keySet) {
System.out.println("processVariables==" + key + ": " + processVariables.get(key));
}
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("approved", true);
// 也能修改已经存在的流程变量
variables.put("description", "有事需请假---修改的哦");
taskService.complete(task.getId(), variables);
}
处理的时候涉及到的表:
act_ru_execution:运行时流程执行实例表,记录运行中流程运行的各个分支信息(当没有子流程时,其数据与act_ru_task表数据是一一对应的);
act_ru_identitylink:运行时流程人员表,重要,常用于查询人员或部门的待办任务时使用;
act_ru_task:运行时流程任务节点表,存储运行中流程的任务节点信息,重要,常用于查询人员或部门的待办任务时使用
act_ru_variable:运行时流程变量数据表,存储运行中的流程各节点的变量信息;
8、完成任务
@Test
public void TestCompleteTask2() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery()
.processInstanceId("22501") //根据流程实例编号查找
.taskAssignee("张三")
.singleResult();
taskService.complete(task.getId());
}
在完成之后,这几个表的对应流程的数据会被删除:
act_ru_execution、act_ru_identitylink、act_ru_task、act_ru_variable