1 Activiti服务架构
1.1 概述

1.2 activiti-cfg.xml
- activiti-cfg.xml是activiti的引擎配置文件,包括:ProcessEngineConfiguration的定义、数据源的定义、事务管理器等,此文件其实就是一个Spring配置文件,下面是一个基本的配置只配置了ProcessEngineConfiguration和数据源。
 
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="username" value="root"/><property name="url"value="jdbc:mysql://192.168.134.100:3306/activiti?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/><property name="password" value="123456"/><property name="maxActive" value="3"/><property name="maxIdle" value="1"/></bean><!-- Activiti单独运行的ProcessEngine配置 --><bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"><!-- 数据源 --><property name="dataSource" ref="dataSource"/><!--activiti数据库表处理策略false(默认值):检查数据库的版本和依赖库的版本,如果不匹配就抛出异常true:构建流程引擎时,执行检查,如果需要就执行更新。如果表不存在,就创建。create-drop:构建流程引擎时创建数据库报表,关闭流程引擎时就删除这些表。drop-create:先删除表再创建表。create:构建流程引擎时创建数据库表,关闭流程引擎时不删除这些表--><property name="databaseSchemaUpdate" value="true"/></bean></beans>
1.3 ProcessEngineConfiguration
1.3.1 概述
- 流程引擎的配置类,通过ProcessEngineConfiguration可以创建工作流引擎ProcessEngine,常用的两种方法如下:
 
1.3.2 StandaloneProcessEngineConfiguration
- 通过org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration,Activiti可以单独运行,使用它创建的ProcessEngine,Activiti会自己处理事务。
 - 配置文件方式:
- 通常在activiti-cfg.xml配置文件中定义一个id为processEngineConfiguration的Bean,这里会使用Spring的依赖注入来构建引擎。
<!-- Activiti单独运行的ProcessEngine配置 --><bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"><!-- 数据源 --><property name="dataSource" ref="dataSource"/><!--activiti数据库表处理策略false(默认值):检查数据库的版本和依赖库的版本,如果不匹配就抛出异常true:构建流程引擎时,执行检查,如果需要就执行更新。如果表不存在,就创建。create-drop:构建流程引擎时创建数据库报表,关闭流程引擎时就删除这些表。drop-create:先删除表再创建表。create:构建流程引擎时创建数据库表,关闭流程引擎时不删除这些表--><property name="databaseSchemaUpdate" value="true"/></bean>
 
 - 通常在activiti-cfg.xml配置文件中定义一个id为processEngineConfiguration的Bean,这里会使用Spring的依赖注入来构建引擎。
 
1.3.3 SpringProcessEngineConfiguration
- 通过org.activiti.spring.SpringProcessEngineConfiguration和Spring整合。
 
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="username" value="root"/><property name="url"value="jdbc:mysql://192.168.134.100:3306/activiti?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/><property name="password" value="123456"/><property name="maxActive" value="3"/><property name="maxIdle" value="1"/></bean><!-- 工作流引擎配置bean --><bean id="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration"><!-- 数据源 --><property name="dataSource" ref="dataSource"/><!-- 使用spring事务管理器 --><property name="transactionManager" ref="transactionManager"/><!-- 数据库策略 --><property name="databaseSchemaUpdate" value="drop-create"/></bean><!-- 流程引擎 --><bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"><property name="processEngineConfiguration"ref="processEngineConfiguration"/></bean><!-- 资源服务service --><bean id="repositoryService" factory-bean="processEngine"factory-method="getRepositoryService" /><!-- 流程运行service --><bean id="runtimeService" factory-bean="processEngine"factory-method="getRuntimeService" /><!-- 任务管理service --><bean id="taskService" factory-bean="processEngine"factory-method="getTaskService" /><!-- 历史管理service --><bean id="historyService" factory-bean="processEngine"factory-method="getHistoryService" /><!-- 引擎管理service --><bean id="managementService" factory-bean="processEngine"factory-method="getManagementService" /><!-- 事务管理器 --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 传播行为 --><tx:method name="save*" propagation="REQUIRED" /><tx:method name="insert*" propagation="REQUIRED" /><tx:method name="delete*" propagation="REQUIRED" /><tx:method name="update*" propagation="REQUIRED" /><tx:method name="find*" propagation="SUPPORTS" read-only="true" /><tx:method name="get*" propagation="SUPPORTS" read-only="true" /></tx:attributes></tx:advice><!-- 切面,根据具体项目修改切点配置 --><aop:config proxy-target-class="true"><aop:advisor advice-ref="txAdvice"pointcut="execution(* com.sunxiaping.*.service.impl.*.*(..))" /></aop:config></beans>
1.3.4 创建ProcessEngineConfiguration
- 下面的方法:要求activiti-cfg.xml中必须由一个processEngineConfiguration的Bean的id。
 
public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource) {return createProcessEngineConfigurationFromResource(resource, "processEngineConfiguration");}
- 下面的方法,可以更改Bean的id。
 
public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource, String beanName) {return BeansConfigurationHelper.parseProcessEngineConfigurationFromResource(resource, beanName);}
1.4 ProcessEngine
- 工作流引擎,相当于一个门面接口,通过ProcessEngineConfiguration创建ProcessEngine,通过ProcessEngine创建各个Service接口。
 
1.4.1 一般创建方式
- 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-07-31 6:41*/public class ActivitiTest {public static void main(String[] args) {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");//创建ProcessEngine对象ProcessEngine processEngine = configuration.buildProcessEngine();System.out.println("processEngine = " + processEngine);}}
1.4.2 简单创建方式
- 将activiti.cfg.xml文件名以及路径固定,且activiti.cfg.xml文件中有processEngineConfiguration的配置,那么可以使用如下代码创建ProcessEngine。
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngines;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-07-31 6:41*/public class ActivitiTest {public static void main(String[] args) {//该方法有限制//①Activiti的配置文件名必须为activiti.cfg.xml//②Bean的id必须是processEngineConfigurationProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();System.out.println("processEngine = " + processEngine);}}
1.5 Service
1.5.1 Service的创建方式
- 通过ProcessEngine创建Service,Service是工作流引擎提供用于进行工作流部署、指定、管理的服务接口。
 - 创建方式如下:
 
package com.sunxiaping;import org.activiti.engine.*;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-07-31 11:55*/public class ActivitiTest {public static void main(String[] args) {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");//创建ProcessEngine对象ProcessEngine processEngine = configuration.buildProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();RuntimeService runtimeService = processEngine.getRuntimeService();TaskService taskService = processEngine.getTaskService();HistoryService historyService = processEngine.getHistoryService();ManagementService managementService = processEngine.getManagementService();System.out.println("repositoryService = " + repositoryService);System.out.println("runtimeService = " + runtimeService);System.out.println("taskService = " + taskService);System.out.println("historyService = " + historyService);System.out.println("managementService = " + managementService);}}
1.5.2 Service总览
| Service接口 | 说明 | 
|---|---|
| RepositoryService | Activiti的资源管理接口 | 
| RuntimeService | Activiti的流程运行管理接口 | 
| TaskService | Activiti的任务管理接口 | 
| HistoryService | Activiti的历史管理接口 | 
| ManagementService | Activiti的引擎管理接口 | 
1.5.3 RepositoryService
- RepositoryService,是Activiti的资源管理接口,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此Service将流程定义文件的内容部署到计算机中。
 - 除了流程部署定义以外还可以做如下的操作:
查询引擎中的发布包和流程定义。
暂停或激活发布包以及对应全部和特定流程定义。暂停意味着它们不能再在执行任务操作了,激活是对应的反向操作。
获取多种资源,像包含在发布包中的文件获引擎自动生成的流程图。
获取流程定义的POJO,可以用解析流程,而不必通过XML。
 
1.5.4 RuntimeService
- RuntimeService是Activiti的流程运行管理接口,可以从这个接口中获取很多关于流程执行相关的信息。
 
1.5.5 TaskService
- TaskService是Activiti的任务管理接口,可以从这个接口中获取任务的信息。
 
1.5.6 HistoryService
- HistoryService是Activiti的历史管理类,可以查询历史信息,执行流程时,引擎会包含很多数据(根据配置),比如流程实例启动时间,任务的参与者,完成任务的时间,每个流程实例的执行路径,等等。
 
1.5.7 ManagementService
- ManagementService是Activiti的引擎管理接口,提供了对Activiti流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于Activiti系统的日常维护。
 
2 Activiti入门体验
2.1 流程定义
2.1.1 画板
- 在IDEA中安装对应的Activiti-Designer(Activiti设计器)插件即可使用,画板中包括以下结点:
- Connection—连接。
 - Event—事件。
 - Task—任务。
 - Gateway—网关。
 - Container—容器。
 - Boundary event—边界事件。
 - Intermediate event—中间事件。
 
 - 流程图设计完毕保存生成.bpmn文件。
 - 本人此时使用的IDEA版本是2020.2,而IDEA中的Activiti设计器插件actiBPM到此时位置已停止更新了。
 

- 本人只能使用Eclipse画流程图。
- Eclipse需要安装Activiti插件,略。
 
 
2.1.2 绘制流程

2.1.3 指定流程定义key
- 流程定义key即流程定义的标识。
 
建议:相同的业务流程,流程定义的key名字定义一样。如果需要创建新的业务流程,则使用新的key。

2.1.4 指定任务负责人
- 为每个任务结点指定负责人,如添加请假单的负责人是张三。
 

2.2 部署流程定义
- 将刚才生成的holiday.bpmn和holiday.png拷贝到项目的resources目录下。
 

- 示例:使用RepositoryService部署流程定义
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.Deployment;import org.junit.Test;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-07-31 11:55*/public class ActivitiDeploymentTest {/*** 部署流程定义:将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中** act_re_deployment 部署信息* act_re_procdef 流程定义的一些信息* act_ge_bytearray 流程定义bpmn文件和png文件*/@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RepositoryService对象RepositoryService repositoryService = processEngine.getRepositoryService();//进行部署Deployment deployment = repositoryService.createDeployment().addClasspathResource("diagram/holiday.bpmn") //添加bpmn资源.addClasspathResource("diagram/holiday.png").name("请假申请流程").deploy(); //部署//输出部署的一些信息String id = deployment.getId();System.out.println("流程部署id = " + id);String name = deployment.getName();System.out.println("流程部署名称 = " + name);}}
2.3 启动一个流程实例
- 流程定义部署在Activiti中之后就可以通过工作流管理业务流程了。
 - 针对该流程,启动一个流程表示发起一个新的请假申请单,这就相当于Java类和Java对象的关系,类定义好之后需要new创建一个对象使用,当然,也可以new多个对象。
 - 对于请假申请流程,张三发起一个请假申请单需要启动一个流程实例,李四发起一个请求申请单也需要启动一个流程实例。
 
关系: 流程定义(BPMN文件)—>流程部署(Activiti的三张表)。 流程实例—>启动流程实例。 类比: 流程定义类似于Java中的类,流程实例类似于Java中的一个实例(对象),所以一个流程定义key对应多个不同的流程实例。
- 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RuntimeService;import org.activiti.engine.runtime.ProcessInstance;import org.junit.Test;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-01 14:35*/public class ActivitiStartProcessInstanceTest {/*** act_hi_actinst 活动实例* act_hi_identitylink 参与者信息* act_hi_procinst 流程实例* act_hi_taskinst 任务实例* act_ru_execution 执行表* act_ru_identitylink 参与者信息* act_ru_task 任务表*/@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RuntimeService对象RuntimeService runtimeService = processEngine.getRuntimeService();//根据流程定义的key启动流程实例ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");//获取流程实例的相关信息String processDefinitionId = processInstance.getProcessDefinitionId();System.out.println("流程定义的id = " + processDefinitionId);String deploymentId = processInstance.getDeploymentId();System.out.println("流程部署的id = " + deploymentId);String id = processInstance.getId();System.out.println("流程实例的id = " + id);String activityId = processInstance.getActivityId();System.out.println("当前活动的id = " + activityId);}}
2.4 任务查询
- 流程启动后,各个任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
 - 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.TaskService;import org.activiti.engine.task.Task;import org.junit.Test;import java.util.List;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-01 15:00*/public class ActivitiTaskTest {/*** act_ru_task*/@Testpublic void test() {//任务负责人String assignee = "张三";//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取TaskService对象TaskService taskService = processEngine.getTaskService();//查询任务列表,根据流程定义的key和任务负责人List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee(assignee).list();//遍历任务列表for (Task task : taskList) {String processDefinitionId = task.getProcessDefinitionId();System.out.println("流程定义id = " + processDefinitionId);String processInstanceId = task.getProcessInstanceId();System.out.println("流程实例id = " + processInstanceId);String assignee1 = task.getAssignee();System.out.println("任务负责人 = " + assignee1);String id = task.getId();System.out.println("任务id = " + id);String name = task.getName();System.out.println("任务名称 = " + name);}}}
2.5 任务处理
- 任务负责人查询待办任务,选择任务进行处理,完成任务。
 - 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.TaskService;import org.activiti.engine.task.Task;import org.junit.Test;import java.util.List;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-01 15:20*/public class ActivitiTaskCompleteTest {/*** act_hi_actinst 活动实例* act_hi_identitylink 参与者信息* act_hi_taskinst 任务实例* act_ru_execution 执行表* act_ru_identitylink 参与者信息* act_ru_task 任务表*/@Testpublic void test() {//任务负责人String assignee = "张三";//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取TaskService对象TaskService taskService = processEngine.getTaskService();//查询任务列表,根据流程定义的key和任务负责人List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee(assignee).list();//遍历任务列表for (Task task : taskList) {String id = task.getId();//完成任务taskService.complete(id);}}}
3 流程定义
3.1 流程定义概述
3.1.1 什么是流程定义?
- 流程定义是按照BPMN2.0标准去描述业务流程,通常使用Activiti-explorer(Activiti控制台)或Activiti-eclipse-designer(Activiti的eclipse设计器)插件对业务流程进行建模,这两种方式都遵循BPMN2.0标准。
 - 如果使用Activiti-eclipse-designer插件完成业务流程建模。可以生成两个文件:.bpmn和.png文件。
 
3.1.2 bpmn文件
- .bpmn文件其实就是XML文件。
 
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"><process id="holiday" name="请假申请流程" isExecutable="true"><startEvent id="startevent2" name="开始"/><userTask id="usertask1" name="填写请假申请单" activiti:assignee="张三"/><sequenceFlow id="flow1" sourceRef="startevent2" targetRef="usertask1"/><userTask id="usertask2" name="部门经理审批" activiti:assignee="李四"/><sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"/><userTask id="usertask3" name="总经理审批" activiti:assignee="王五"/><sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"/><endEvent id="endevent1" name="结束"/><sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"/></process><bpmndi:BPMNDiagram id="BPMNDiagram_holiday"><bpmndi:BPMNPlane bpmnElement="holiday" id="BPMNPlane_holiday"><bpmndi:BPMNShape bpmnElement="startevent2" id="BPMNShape_startevent2"><omgdc:Bounds height="35.0" width="35.0" x="100.0" y="160.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"><omgdc:Bounds height="55.0" width="105.0" x="180.0" y="150.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"><omgdc:Bounds height="55.0" width="105.0" x="330.0" y="150.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3"><omgdc:Bounds height="55.0" width="105.0" x="480.0" y="150.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"><omgdc:Bounds height="35.0" width="35.0" x="630.0" y="160.0"/></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"><omgdi:waypoint x="135.0" y="177.0"/><omgdi:waypoint x="180.0" y="177.0"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"><omgdi:waypoint x="285.0" y="177.0"/><omgdi:waypoint x="330.0" y="177.0"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"><omgdi:waypoint x="435.0" y="177.0"/><omgdi:waypoint x="480.0" y="177.0"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"><omgdi:waypoint x="585.0" y="177.0"/><omgdi:waypoint x="630.0" y="177.0"/></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>
- .bpmn文件的根节点是definitions节点。这个元素中,可以定义多个流程定义(建议每个文件只包含一个流程定义,可以简化开发过程中的维护难度)。注意,definitions元素最少也要包含xmlns和targetNamespace的声明。targetNamespace可以是任何值,它用来对流程实例进行分类。
 - 流程定义部分:定义了流程每个结点的描述和结点之间的流程流转。
 - 流程布局定义:定义流程每个结点在流程图上的位置坐标等信息。
 
3.1.3 png图片文件
- 如果是在Eclipse中,需要进行如下的配置:
 

3.2 流程定义部署
3.2.1 什么是流程定义部署
- 将生成的流程定义部署到Activiti的数据库中,这就是流程定义部署,通过调用Activiti的API将流程定义的bpmn和png两个文件一个一个添加部署到Activiti中,也可以将两个文件打成zip包进行部署。
 
3.2.2 单个文件部署方式
- 分别将bpmn文件和png图片文件部署。
 - 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.Deployment;import org.junit.Test;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-07-31 11:55*/public class ActivitiDeploymentTest {/*** 部署流程定义:将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中** act_re_deployment 部署信息* act_re_procdef 流程定义的一些信息* act_ge_bytearray 流程定义bpmn文件和png文件*/@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RepositoryService对象RepositoryService repositoryService = processEngine.getRepositoryService();//进行部署Deployment deployment = repositoryService.createDeployment().addClasspathResource("diagram/holiday.bpmn") //添加bpmn资源.addClasspathResource("diagram/holiday.png").name("请假申请流程").deploy(); //部署//输出部署的一些信息String id = deployment.getId();System.out.println("流程部署id = " + id);String name = deployment.getName();System.out.println("流程部署名称 = " + name);}}
3.2.3 压缩包部署方式
- 将.bpmn文件和.png图片压缩成一个zip包。
 

- 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.Deployment;import org.junit.Test;import java.io.InputStream;import java.util.zip.ZipInputStream;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-07-31 11:55*/public class ActivitiZipDeploymentTest {/*** 部署流程定义:将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中** act_re_deployment 部署信息* act_re_procdef 流程定义的一些信息* act_ge_bytearray 流程定义bpmn文件和png文件*/@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RepositoryService对象RepositoryService repositoryService = processEngine.getRepositoryService();InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("diagram/holiday.zip");ZipInputStream zipInputStream = new ZipInputStream(inputStream);//进行部署Deployment deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).name("请假申请流程").deploy(); //部署//输出部署的一些信息String id = deployment.getId();System.out.println("流程部署id = " + id);String name = deployment.getName();System.out.println("流程部署名称 = " + name);}}
3.2.4 操作数据表
- 流程定义部署后,会操作三张表:
act_re_deployment、act_re_procdef和act_ge_bytearray。 act_re_deployment是流程定义部署表,记录流程部署信息。act_re_procdef是流程定义表,记录流程定义信息。act_ge_bytearray是资源表,将.bpmn文件和.png图片存入到这个表。
说明:
act_re_deployment和act_re_procdef是一对多的关系,一次部署在流程部署表生成一条记录,但一次流程部署可以部署多个流程定义,每个流程定义在流程定义表生成一条记录。每一个流程定义在act_ge_bytearray会存在两个资源记录.bpmn文件和.png图片。建议:
- 一次部署一个流程,这样部署表和流程定义表示一对一的关系,方便读取流程部署和流程定义信息。
 
3.3 流程定义查询
- 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.ProcessDefinition;import org.activiti.engine.repository.ProcessDefinitionQuery;import org.junit.Test;import java.util.List;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-01 21:24*/public class ActivitiProcessDefinitionQueryTest {/*** 查询流程定义信息*/@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RepositoryService对象RepositoryService repositoryService = processEngine.getRepositoryService();//得到ProcessDefinitionQuery对象ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();//设置条件,并查询出当前的所有流程定义List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list();//输出流程定义信息for (ProcessDefinition processDefinition : processDefinitionList) {System.out.println("流程定义的id = " + processDefinition.getId());System.out.println("流程定义的name = " + processDefinition.getName());System.out.println("流程定义的key = " + processDefinition.getKey());System.out.println("流程定义的version = " + processDefinition.getVersion());}}}
3.4 流程定义删除
- 示例:
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.junit.Test;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-01 21:13*/public class ActivitiDeleteProcessDefinitionTest {/*** 删除已经部署的流程定义** 注意事项:* ①当我们正在执行的这一套流程没有结束,此时如果要删除流程定义信息就会失败(调用void deleteDeployment(String deploymentId)方法)。* ②当我们正在执行的这一套流程没有结束,此时如果要强制删除流程定义信息,需要调用void deleteDeployment(String deploymentId, boolean cascade)这个方式,将cascade设置为true。*/@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RepositoryService对象RepositoryService repositoryService = processEngine.getRepositoryService();//删除已经部署的流程定义String deploymentId = "1";repositoryService.deleteDeployment(deploymentId);}}
3.5 流程定义资源查询
- 示例:通过查询流程定义对象获取流程定义资源,即bpmn和png
 
package com.sunxiaping;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.ProcessDefinition;import org.activiti.engine.repository.ProcessDefinitionQuery;import org.junit.Test;import org.springframework.util.FileCopyUtils;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.List;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-02 10:22*/public class ActivitiResourceTest {@Testpublic void test() throws IOException {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();//获取RepositoryService对象RepositoryService repositoryService = processEngine.getRepositoryService();//获取ProcessDefinitionQuery对象ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();//设置查询条件,执行查询操作List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list();//遍历查询结果for (ProcessDefinition processDefinition : processDefinitionList) {//获取资源名称,即png图片的名称String resourceName = processDefinition.getResourceName();//获取图表资源,即bpmn图片的名称String diagramResourceName = processDefinition.getDiagramResourceName();//获取资源的输入流,即png图片的输入流InputStream resourceNameInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);InputStream diagramResourceNameInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), diagramResourceName);String resourcePath = "d:" + File.separator + resourceName;File file = new File(resourcePath);if (!file.exists()) {file.getParentFile().mkdirs();}String diagramResourcePath = "d:" + File.separator + diagramResourceName;file = new File(diagramResourcePath);if (!file.exists()) {file.getParentFile().mkdirs();}//复制文件FileCopyUtils.copy(resourceNameInputStream, new FileOutputStream(resourcePath));FileCopyUtils.copy(diagramResourceNameInputStream, new FileOutputStream(diagramResourcePath));}}}
3.6 流程历史信息查询
- 示例:
 
package com.sunxiaping;import org.activiti.engine.HistoryService;import org.activiti.engine.ProcessEngine;import org.activiti.engine.ProcessEngineConfiguration;import org.activiti.engine.history.HistoricActivityInstance;import org.activiti.engine.history.HistoricActivityInstanceQuery;import org.junit.Test;import java.util.List;/*** @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>* @version 1.0* 2020-08-01 21:13*/public class ActivitiHistoryTest {@Testpublic void test() {//创建ProcessEngineConfiguration对象ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");//获取ProcessEngine对象ProcessEngine processEngine = configuration.buildProcessEngine();//获取HistoryService对象HistoryService historyService = processEngine.getHistoryService();//获取HistoricActivityInstanceQuery查询对象HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();List<HistoricActivityInstance> historicActivityInstanceList = historicActivityInstanceQuery.list();for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {String activityId = historicActivityInstance.getActivityId();System.out.println("activityId = " + activityId);String activityName = historicActivityInstance.getActivityName();System.out.println("activityName = " + activityName);String processDefinitionId = historicActivityInstance.getProcessDefinitionId();System.out.println("processDefinitionId = " + processDefinitionId);String processInstanceId = historicActivityInstance.getProcessInstanceId();System.out.println("processInstanceId = " + processInstanceId);}}}
