一、简介
Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务
流程图。
二、Activiti数据库支持
Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
- ACT_RE_*: ‘RE’ 表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
- ACT_RU_*: ‘RU’ 表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
- ACT_ID_*: ‘ID’ 表示 identity。 这些表包含身份信息,比如用户,组等等。
- ACT_HI_*: ‘HI’ 表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
- ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。
- 资源库流程规则表
act_re_deployment | 部署信息表 |
act_re_model | 流程设计模型部署表 |
act_re_procdef | 流程定义数据表 |
- 运行时数据库表
act_ru_execution | 运行时流程执行实例表 |
act_ru_identitylink | 运行时流程人员表,主要存储任务节点与参与者的相关信息 |
act_ru_task | 运行时任务节点表 |
act_ru_variable | 运行时流程变量数据表 |
- 历史数据库表
act_hi_actinst | 历史节点表 |
act_hi_attachment | 历史附件表 |
act_hi_comment | 历史意见表 |
act_hi_identitylink | 历史流程人员表 |
act_hi_detail | 历史详情表,提供历史变量的查询 |
act_hi_procinst | 历史流程实例表 |
act_hi_taskinst | 历史任务实例表 |
act_hi_varinst | 历史变量表 |
- 组织机构表
act_id_group | 用户组信息表 |
act_id_info | 用户扩展信息表 |
act_id_membership | 用户与用户组对应信息表 |
act_id_user | 用户信息表 |
- 通用数据表
act_ge_bytearray | 二进制数据表 |
act_ge_property | 属性数据表,存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录 |
以上数据库表都不是一开始就存在的,也不需要用户手动创建,可以通过代码的方式自动生成,一下有三种初始化数据库的方式:
不管是哪种方式,首先都需要导包,添加 Activiti5 的 jar 包,在 activiti-5.13->wars 目录下是一些示例项目,解压 activiti-rest 项目,导入 activiti-rest 目录中 WEB-INF\lib 下所有包。添加到 classpath 中。另外还需要添加数据库连接的 jar 包。
在Activiti中,在创建核心的流程引擎对象时会自动建表。
1. JDBC 方式
private static void fun1() {
//JDBC 方式
ProcessEngineConfiguration processEngineConfiguration =
ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//配置连接数据库信息
processEngineConfiguration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti_demo?nullCatalogMeansCurrent=true");
processEngineConfiguration.setJdbcUsername("root");
processEngineConfiguration.setJdbcPassword("123456");
//配置建表策略
processEngineConfiguration.setDatabaseSchemaUpdate("true");
//使用流程引擎配置对象创建 流程引擎对象
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
System.out.println(processEngine);
}
这里有一个 activiti 的坑,如果使用的是 MySQL8 版本数据库的话,需要在连接数据库的 url 中添加 nullCatalogMeansCurrent=true,否则不会自动生成 activiti 的 23 张表。
2. Spring 方式:添加并制定配置文件
创建一个类似spring结构的配置文件,一般命名为 activiti.cfg.xml,用来做流程引擎的相关配置。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean name="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--配置连接数据库信息-->
<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti_demo?nullCatalogMeansCurrent=true"></property>
<property name="jdbcUsername" value="root"></property>
<property name="JdbcPassword" value="123456"></property>
<!--配置建表策略-->
<property name="databaseSchemaUpdate" value="true"></property>
</bean>
</beans>
private static void fun2() {
//Spring 方式
ProcessEngineConfiguration processEngineConfiguration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
System.out.println(processEngine);
}
3. 快速创建方式(开发中常用)
同样需要 Spring 方式的 activiti.cfg.xml 配置文件,但是 Java 代码中可以使用默认的方式生成对象: ProcessEngines.getDefaultProcessEngine()。在该方法中,会默认读取名为 activiti.cfg.xml 的配置文件。
private static void fun3() {
//快速创建方式,开发中常用
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
}
三、核心 API
1. ProcessEngine(流程引擎):Activiti中最核心的类,其他的类都是由他而来。
- RepositoryService:processEngine.getRepositoryService();
- RuntimeService:processEngine.getRuntimeService();
- TaskService:processEngine.getTaskService();
RepositoryService | 管理流程定义 |
RuntimeService | 执行管理,包括启动、推进、删除流程实例等操作 |
TaskService | 任务管理 |
HistoryService | 历史管理(执行完的数据的管理) |
IdentityService | 组织机构管理 |
2. RepositoryService:Activiti的仓库服务类。所谓的仓库指流程定义文档的两个文件:bpmn文件和流程图片。用于操作数据库中表名为 * _ re _ * 的表。
- DeploymentBuilder:repositoryService.createDeployment();创建部署流程对象。
- name(“流程名称”):给部署的流程设置名称;
- addClasspathResource("*.bpmn / *.png"):第一种方式添加 bpnm 和 png 文件;
- addZipInputStream(zipInputStream):通过 IO 流的方式读取 bpnm 和 png 的 .zip 文件;
- deploy():部署流程。
- 删除流程定义:repositoryService.deleteDeployment(id)/deleteDeployment(id, true);参数 id 为部署流程 id,普通删除时若流程正在执行则不会被删除;设置级连删除时调用另一个重载方法,设置参数为 true 表示开启级连,级连删除时即使流程正在执行也会被删除。
- DeploymentQuery:repositoryService.createDeploymentQuery();创建部署流程的查询对象。
- getId():获取部署流程 id;
- getName():获取部署流程名称。
- list():获取所有信息,返回 list 集合;
- singleResult():获取单个信息,返回相应类型的对象。
- ProcessDefinitionQuery:repositoryService.createProcessDefinitionQuery();创建流程定义的查询对象。操作一组 ProcessDefinition 对象。
- getDeploymentId():获取部署流程 id;
- getName():获取业务流程图的 name;
- getResourceName():获取资源文件 bpmn 的名称;
- getDiagramResourceName():获取资源文件 png 的名称
- getId():获取流程定义 id;
- getVersion():获取流程定义版本号;
- getKey():获取业务流程图的 id;
- list():获取所有信息,返回 list 集合;
- singleResult():获取单个信息,返回相应类型的对象。
DeploymentBuilder | 用来定义流程部署的相关参数 |
删除流程定义 | 分为普通删除与级连删除 |
DeploymentQuery | 用来查询流程部署列表(* _ re _ deployment) |
ProcessDefinitionQuery | 用来查询流程定义列表(* _ re _ procdef) |
3. RuntimeService:Activiti的流程执行服务类。可以从这个服务类中获取很多关于流程执行相关的信息。
- ProcessInstance:runtimeService.startProcessInstanceByKey(processDefinitionKey);启动流程并创建一个流程实例对象,processDefinitionKey 为定义业务流程图是设置的 id。
- getProcessDefinitionId():获取流程定义 id;
- getProcessInstanceId():获取流程实例 id。
- getBusinessKey():获取 BusinessKey ,BusinessKey 是存放用户自定义的 key;
- ProcessInstanceQuery:runtimeService.createProcessInstanceQuery();创建流程实例的查询对象。可以操作一组 ProcessInstance 对象。
ProcessInstance | 流程实例对象,在启动流程时会创建唯一的流程实例对象管理当前启动的流程 |
ProcessInstanceQuery | 用来查询流程实例列表(* _ ru _ execution) |
4. TaskService:Activiti的任务服务类。可以从这个类中获取任务的信息。
- TaskQuery:taskService.createTaskQuery();创建任务查询对象,操作任务列表信息。
- list():获取所有信息,返回 list 集合;
- singleResult():获取单个信息,返回相应类型的对象。
- 添加批注信息:taskService.addComment(taskId, processInstanceId, message),参数分别为任务 id,流程实例 id,以及要写入的批注信息。
- 完成指定任务:taskService.complete(taskId),根据传入任务 id 完成指定任务。
5. HistoryService:Activiti的查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息。
- HistoricTaskInstanceQuery:historyService.createHistoricTaskInstanceQuery();创建历史任务的查询对象,用于查询历史任务信息。
- HistoricProcessInstanceQuery:historyService.createHistoricProcessInstanceQuery();创建历史流程实例的查询对象,用于查询历史流程实例的信息。
- HistoricVariableInstanceQuery:historyService.createHistoricVariableInstanceQuery();创建历史流程变量的查询对象,用于查询历史变量的信息。
HistoricTaskInstanceQuery | 用于查询历史任务信息 |
HistoricProcessInstanceQuery | 用于查询历史流程实例的信息 |
HistoricVariableInstanceQuery | 用于查询历史变量的信息 |
6. ProcessDefinition:流程定义类。可以从这里获得资源文件等。
- 通过部署流程 id 获取资源文件:
- repositoryService.getDeploymentResourceNames(deploymentId),返回 list 集合,包含 bpmn 和 png 两个资源名称。
- 遍历集合获取 png 资源名称;
- repositoryService.getResourceAsStream(deploymentId, sourceName),以流的方式读取指定资源,返回 InputStream.
- 通过任务 id 获取资源文件:
- taskService.createTaskQuery().taskId(taskId).singleResult(),根据任务 id 获取到任务对象 task;
- task.getProcessDefinitionId(),由任务对象获取到流程定义 id;
- repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId),由流程定义 id 获取到流程定义对象;
- processDefinition.getDeploymentId(),processDefinition.getDiagramResourceName(),由流程定义对象获取到部署流程 id 和资源名称。
- repositoryService.getResourceAsStream(deploymentId, sourceName),以流的方式读取指定资源,返回 InputStream.
四、流程变量
优点:
(1)从一个任务节点到另一个任务节点的时候,想要带参数到另一个节点,就要用到流程变量;
(2)在有多条分支的情况下,可以使用流程节点控制任务节点的流向。
- 情况一的使用:作为参数传递
- 在一个任务节点完成任务之前,设置好需要传递的参数,例如,taskService().setVariable(taskId, “money”, 1000),通过 taskId 给指定任务添加流程变量。
- 另外也可以传递 map 集合,map 集合中保存多个需要传递的参数,调用相应的重载方法设置,例如,taskService().complete(taskId, map);
- 情况二的使用:控制任务节点的流向
- 在流程图的连线中设置条件,当满足条件时沿着该路线走;
- 在当前节点完成前,设置传递的参数,传递的参数需要与条件一致;
- 当前任务完成后,会比较传入的参数满足那一条路线的条件。
- 待办人处理:
- 直接写死在流程中;
- 通过表达式设置,在任务推进时使用流程变量设置待办人;
- 监听器方式设置:activiti + ssm 的项目中使用监听器方式设置待办人
(1)自定义一个类实现 TaskListener 接口,重写 notify(DelegateTask delegateTask) 方法;
(2)获取 Spring 容器:WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
(3)获取 bean :EmployeeService employeeService = (EmployeeService) context.getBean(“employeeService”);
(4)获取 request 对象:HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
(5)从 session 中获取当前待办人:Employee employee = (Employee) request.getSession().getAttribute(“employee_session”);
(6)根据当前待办人查询下一个待办人:Employee manager = employeeService.findManagerByManagerId(employee.getManagerId());
(7)设置待办人信息:delegateTask.setAssignee(manager.getName());
五、网关
Activiti 中的网关:Gateway
- Activiti 中的网关分类:
- 排他网关:当前节点完成后有多条路线时,自会选择其中一条路线执行下去。
- 并行网关:当前节点完成后有多条路线,可以并行执行多条路线,然后再合并。