1 Activiti服务架构

1.1 概述

Activiti服务架构图.jpg

1.2 activiti-cfg.xml

  • activiti-cfg.xml是activiti的引擎配置文件,包括:ProcessEngineConfiguration的定义、数据源的定义、事务管理器等,此文件其实就是一个Spring配置文件,下面是一个基本的配置只配置了ProcessEngineConfiguration和数据源。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns="http://www.springframework.org/schema/beans"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context.xsd">
  9. <!-- 配置数据源 -->
  10. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  11. <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
  12. <property name="username" value="root"/>
  13. <property name="url"
  14. value="jdbc:mysql://192.168.134.100:3306/activiti?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
  15. <property name="password" value="123456"/>
  16. <property name="maxActive" value="3"/>
  17. <property name="maxIdle" value="1"/>
  18. </bean>
  19. <!-- Activiti单独运行的ProcessEngine配置 -->
  20. <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
  21. <!-- 数据源 -->
  22. <property name="dataSource" ref="dataSource"/>
  23. <!--
  24. activiti数据库表处理策略
  25. false(默认值):检查数据库的版本和依赖库的版本,如果不匹配就抛出异常
  26. true:构建流程引擎时,执行检查,如果需要就执行更新。如果表不存在,就创建。
  27. create-drop:构建流程引擎时创建数据库报表,关闭流程引擎时就删除这些表。
  28. drop-create:先删除表再创建表。
  29. create:构建流程引擎时创建数据库表,关闭流程引擎时不删除这些表
  30. -->
  31. <property name="databaseSchemaUpdate" value="true"/>
  32. </bean>
  33. </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的依赖注入来构建引擎。
      1. <!-- Activiti单独运行的ProcessEngine配置 -->
      2. <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
      3. <!-- 数据源 -->
      4. <property name="dataSource" ref="dataSource"/>
      5. <!--
      6. activiti数据库表处理策略
      7. false(默认值):检查数据库的版本和依赖库的版本,如果不匹配就抛出异常
      8. true:构建流程引擎时,执行检查,如果需要就执行更新。如果表不存在,就创建。
      9. create-drop:构建流程引擎时创建数据库报表,关闭流程引擎时就删除这些表。
      10. drop-create:先删除表再创建表。
      11. create:构建流程引擎时创建数据库表,关闭流程引擎时不删除这些表
      12. -->
      13. <property name="databaseSchemaUpdate" value="true"/>
      14. </bean>

1.3.3 SpringProcessEngineConfiguration

  • 通过org.activiti.spring.SpringProcessEngineConfiguration和Spring整合。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. http://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">
  10. <!-- 配置数据源 -->
  11. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  12. <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
  13. <property name="username" value="root"/>
  14. <property name="url"
  15. value="jdbc:mysql://192.168.134.100:3306/activiti?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
  16. <property name="password" value="123456"/>
  17. <property name="maxActive" value="3"/>
  18. <property name="maxIdle" value="1"/>
  19. </bean>
  20. <!-- 工作流引擎配置bean -->
  21. <bean id="processEngineConfiguration"
  22. class="org.activiti.spring.SpringProcessEngineConfiguration">
  23. <!-- 数据源 -->
  24. <property name="dataSource" ref="dataSource"/>
  25. <!-- 使用spring事务管理器 -->
  26. <property name="transactionManager" ref="transactionManager"/>
  27. <!-- 数据库策略 -->
  28. <property name="databaseSchemaUpdate" value="drop-create"/>
  29. </bean>
  30. <!-- 流程引擎 -->
  31. <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
  32. <property name="processEngineConfiguration"
  33. ref="processEngineConfiguration"/>
  34. </bean>
  35. <!-- 资源服务service -->
  36. <bean id="repositoryService" factory-bean="processEngine"
  37. factory-method="getRepositoryService" />
  38. <!-- 流程运行service -->
  39. <bean id="runtimeService" factory-bean="processEngine"
  40. factory-method="getRuntimeService" />
  41. <!-- 任务管理service -->
  42. <bean id="taskService" factory-bean="processEngine"
  43. factory-method="getTaskService" />
  44. <!-- 历史管理service -->
  45. <bean id="historyService" factory-bean="processEngine"
  46. factory-method="getHistoryService" />
  47. <!-- 引擎管理service -->
  48. <bean id="managementService" factory-bean="processEngine"
  49. factory-method="getManagementService" />
  50. <!-- 事务管理器 -->
  51. <bean id="transactionManager"
  52. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  53. <property name="dataSource" ref="dataSource" />
  54. </bean>
  55. <!-- 通知 -->
  56. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  57. <tx:attributes>
  58. <!-- 传播行为 -->
  59. <tx:method name="save*" propagation="REQUIRED" />
  60. <tx:method name="insert*" propagation="REQUIRED" />
  61. <tx:method name="delete*" propagation="REQUIRED" />
  62. <tx:method name="update*" propagation="REQUIRED" />
  63. <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
  64. <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
  65. </tx:attributes>
  66. </tx:advice>
  67. <!-- 切面,根据具体项目修改切点配置 -->
  68. <aop:config proxy-target-class="true">
  69. <aop:advisor advice-ref="txAdvice"
  70. pointcut="execution(* com.sunxiaping.*.service.impl.*.*(..))" />
  71. </aop:config>
  72. </beans>

1.3.4 创建ProcessEngineConfiguration

  • 下面的方法:要求activiti-cfg.xml中必须由一个processEngineConfiguration的Bean的id。
  1. public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource) {
  2. return createProcessEngineConfigurationFromResource(resource, "processEngineConfiguration");
  3. }
  • 下面的方法,可以更改Bean的id。
  1. public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource, String beanName) {
  2. return BeansConfigurationHelper.parseProcessEngineConfigurationFromResource(resource, beanName);
  3. }

1.4 ProcessEngine

  • 工作流引擎,相当于一个门面接口,通过ProcessEngineConfiguration创建ProcessEngine,通过ProcessEngine创建各个Service接口。

1.4.1 一般创建方式

  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. /**
  5. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  6. * @version 1.0
  7. * 2020-07-31 6:41
  8. */
  9. public class ActivitiTest {
  10. public static void main(String[] args) {
  11. //创建ProcessEngineConfiguration对象
  12. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
  13. //创建ProcessEngine对象
  14. ProcessEngine processEngine = configuration.buildProcessEngine();
  15. System.out.println("processEngine = " + processEngine);
  16. }
  17. }

1.4.2 简单创建方式

  • 将activiti.cfg.xml文件名以及路径固定,且activiti.cfg.xml文件中有processEngineConfiguration的配置,那么可以使用如下代码创建ProcessEngine。
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngines;
  4. /**
  5. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  6. * @version 1.0
  7. * 2020-07-31 6:41
  8. */
  9. public class ActivitiTest {
  10. public static void main(String[] args) {
  11. //该方法有限制
  12. //①Activiti的配置文件名必须为activiti.cfg.xml
  13. //②Bean的id必须是processEngineConfiguration
  14. ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
  15. System.out.println("processEngine = " + processEngine);
  16. }
  17. }

1.5 Service

1.5.1 Service的创建方式

  • 通过ProcessEngine创建Service,Service是工作流引擎提供用于进行工作流部署、指定、管理的服务接口。
  • 创建方式如下:
  1. package com.sunxiaping;
  2. import org.activiti.engine.*;
  3. /**
  4. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  5. * @version 1.0
  6. * 2020-07-31 11:55
  7. */
  8. public class ActivitiTest {
  9. public static void main(String[] args) {
  10. //创建ProcessEngineConfiguration对象
  11. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  12. //创建ProcessEngine对象
  13. ProcessEngine processEngine = configuration.buildProcessEngine();
  14. RepositoryService repositoryService = processEngine.getRepositoryService();
  15. RuntimeService runtimeService = processEngine.getRuntimeService();
  16. TaskService taskService = processEngine.getTaskService();
  17. HistoryService historyService = processEngine.getHistoryService();
  18. ManagementService managementService = processEngine.getManagementService();
  19. System.out.println("repositoryService = " + repositoryService);
  20. System.out.println("runtimeService = " + runtimeService);
  21. System.out.println("taskService = " + taskService);
  22. System.out.println("historyService = " + historyService);
  23. System.out.println("managementService = " + managementService);
  24. }
  25. }

1.5.2 Service总览

Service接口 说明
RepositoryService Activiti的资源管理接口
RuntimeService Activiti的流程运行管理接口
TaskService Activiti的任务管理接口
HistoryService Activiti的历史管理接口
ManagementService Activiti的引擎管理接口

1.5.3 RepositoryService

  • RepositoryService,是Activiti的资源管理接口,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此Service将流程定义文件的内容部署到计算机中。
  • 除了流程部署定义以外还可以做如下的操作:
    • Activiti7工作流的使用 - 图2查询引擎中的发布包和流程定义。
    • Activiti7工作流的使用 - 图3暂停或激活发布包以及对应全部和特定流程定义。暂停意味着它们不能再在执行任务操作了,激活是对应的反向操作。
    • Activiti7工作流的使用 - 图4获取多种资源,像包含在发布包中的文件获引擎自动生成的流程图。
    • Activiti7工作流的使用 - 图5获取流程定义的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到此时位置已停止更新了。

actiBPM插件停止更新了.png

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

2.1.2 绘制流程

绘制流程.png

2.1.3 指定流程定义key

  • 流程定义key即流程定义的标识。

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

指定流程定义key.png

2.1.4 指定任务负责人

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

指定任务负责人.png

2.2 部署流程定义

  • 将刚才生成的holiday.bpmn和holiday.png拷贝到项目的resources目录下。

拷贝生成的bpmn和png文件.png

  • 示例:使用RepositoryService部署流程定义
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RepositoryService;
  5. import org.activiti.engine.repository.Deployment;
  6. import org.junit.Test;
  7. /**
  8. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  9. * @version 1.0
  10. * 2020-07-31 11:55
  11. */
  12. public class ActivitiDeploymentTest {
  13. /**
  14. * 部署流程定义:将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中
  15. *
  16. * act_re_deployment 部署信息
  17. * act_re_procdef 流程定义的一些信息
  18. * act_ge_bytearray 流程定义bpmn文件和png文件
  19. */
  20. @Test
  21. public void test() {
  22. //创建ProcessEngineConfiguration对象
  23. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  24. ProcessEngine processEngine = configuration.buildProcessEngine();
  25. //获取RepositoryService对象
  26. RepositoryService repositoryService = processEngine.getRepositoryService();
  27. //进行部署
  28. Deployment deployment = repositoryService.createDeployment()
  29. .addClasspathResource("diagram/holiday.bpmn") //添加bpmn资源
  30. .addClasspathResource("diagram/holiday.png")
  31. .name("请假申请流程")
  32. .deploy(); //部署
  33. //输出部署的一些信息
  34. String id = deployment.getId();
  35. System.out.println("流程部署id = " + id);
  36. String name = deployment.getName();
  37. System.out.println("流程部署名称 = " + name);
  38. }
  39. }

2.3 启动一个流程实例

  • 流程定义部署在Activiti中之后就可以通过工作流管理业务流程了。
  • 针对该流程,启动一个流程表示发起一个新的请假申请单,这就相当于Java类和Java对象的关系,类定义好之后需要new创建一个对象使用,当然,也可以new多个对象。
  • 对于请假申请流程,张三发起一个请假申请单需要启动一个流程实例,李四发起一个请求申请单也需要启动一个流程实例。

关系: 流程定义(BPMN文件)—>流程部署(Activiti的三张表)。 流程实例—>启动流程实例。 类比: 流程定义类似于Java中的类,流程实例类似于Java中的一个实例(对象),所以一个流程定义key对应多个不同的流程实例。

  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RuntimeService;
  5. import org.activiti.engine.runtime.ProcessInstance;
  6. import org.junit.Test;
  7. /**
  8. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  9. * @version 1.0
  10. * 2020-08-01 14:35
  11. */
  12. public class ActivitiStartProcessInstanceTest {
  13. /**
  14. * act_hi_actinst 活动实例
  15. * act_hi_identitylink 参与者信息
  16. * act_hi_procinst 流程实例
  17. * act_hi_taskinst 任务实例
  18. * act_ru_execution 执行表
  19. * act_ru_identitylink 参与者信息
  20. * act_ru_task 任务表
  21. */
  22. @Test
  23. public void test() {
  24. //创建ProcessEngineConfiguration对象
  25. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  26. ProcessEngine processEngine = configuration.buildProcessEngine();
  27. //获取RuntimeService对象
  28. RuntimeService runtimeService = processEngine.getRuntimeService();
  29. //根据流程定义的key启动流程实例
  30. ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");
  31. //获取流程实例的相关信息
  32. String processDefinitionId = processInstance.getProcessDefinitionId();
  33. System.out.println("流程定义的id = " + processDefinitionId);
  34. String deploymentId = processInstance.getDeploymentId();
  35. System.out.println("流程部署的id = " + deploymentId);
  36. String id = processInstance.getId();
  37. System.out.println("流程实例的id = " + id);
  38. String activityId = processInstance.getActivityId();
  39. System.out.println("当前活动的id = " + activityId);
  40. }
  41. }

2.4 任务查询

  • 流程启动后,各个任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.TaskService;
  5. import org.activiti.engine.task.Task;
  6. import org.junit.Test;
  7. import java.util.List;
  8. /**
  9. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  10. * @version 1.0
  11. * 2020-08-01 15:00
  12. */
  13. public class ActivitiTaskTest {
  14. /**
  15. * act_ru_task
  16. */
  17. @Test
  18. public void test() {
  19. //任务负责人
  20. String assignee = "张三";
  21. //创建ProcessEngineConfiguration对象
  22. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  23. ProcessEngine processEngine = configuration.buildProcessEngine();
  24. //获取TaskService对象
  25. TaskService taskService = processEngine.getTaskService();
  26. //查询任务列表,根据流程定义的key和任务负责人
  27. List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee(assignee).list();
  28. //遍历任务列表
  29. for (Task task : taskList) {
  30. String processDefinitionId = task.getProcessDefinitionId();
  31. System.out.println("流程定义id = " + processDefinitionId);
  32. String processInstanceId = task.getProcessInstanceId();
  33. System.out.println("流程实例id = " + processInstanceId);
  34. String assignee1 = task.getAssignee();
  35. System.out.println("任务负责人 = " + assignee1);
  36. String id = task.getId();
  37. System.out.println("任务id = " + id);
  38. String name = task.getName();
  39. System.out.println("任务名称 = " + name);
  40. }
  41. }
  42. }

2.5 任务处理

  • 任务负责人查询待办任务,选择任务进行处理,完成任务。
  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.TaskService;
  5. import org.activiti.engine.task.Task;
  6. import org.junit.Test;
  7. import java.util.List;
  8. /**
  9. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  10. * @version 1.0
  11. * 2020-08-01 15:20
  12. */
  13. public class ActivitiTaskCompleteTest {
  14. /**
  15. * act_hi_actinst 活动实例
  16. * act_hi_identitylink 参与者信息
  17. * act_hi_taskinst 任务实例
  18. * act_ru_execution 执行表
  19. * act_ru_identitylink 参与者信息
  20. * act_ru_task 任务表
  21. */
  22. @Test
  23. public void test() {
  24. //任务负责人
  25. String assignee = "张三";
  26. //创建ProcessEngineConfiguration对象
  27. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  28. ProcessEngine processEngine = configuration.buildProcessEngine();
  29. //获取TaskService对象
  30. TaskService taskService = processEngine.getTaskService();
  31. //查询任务列表,根据流程定义的key和任务负责人
  32. List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee(assignee).list();
  33. //遍历任务列表
  34. for (Task task : taskList) {
  35. String id = task.getId();
  36. //完成任务
  37. taskService.complete(id);
  38. }
  39. }
  40. }

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文件。
  1. <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">
  2. <process id="holiday" name="请假申请流程" isExecutable="true">
  3. <startEvent id="startevent2" name="开始"/>
  4. <userTask id="usertask1" name="填写请假申请单" activiti:assignee="张三"/>
  5. <sequenceFlow id="flow1" sourceRef="startevent2" targetRef="usertask1"/>
  6. <userTask id="usertask2" name="部门经理审批" activiti:assignee="李四"/>
  7. <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"/>
  8. <userTask id="usertask3" name="总经理审批" activiti:assignee="王五"/>
  9. <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"/>
  10. <endEvent id="endevent1" name="结束"/>
  11. <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"/>
  12. </process>
  13. <bpmndi:BPMNDiagram id="BPMNDiagram_holiday">
  14. <bpmndi:BPMNPlane bpmnElement="holiday" id="BPMNPlane_holiday">
  15. <bpmndi:BPMNShape bpmnElement="startevent2" id="BPMNShape_startevent2">
  16. <omgdc:Bounds height="35.0" width="35.0" x="100.0" y="160.0"/>
  17. </bpmndi:BPMNShape>
  18. <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
  19. <omgdc:Bounds height="55.0" width="105.0" x="180.0" y="150.0"/>
  20. </bpmndi:BPMNShape>
  21. <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
  22. <omgdc:Bounds height="55.0" width="105.0" x="330.0" y="150.0"/>
  23. </bpmndi:BPMNShape>
  24. <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
  25. <omgdc:Bounds height="55.0" width="105.0" x="480.0" y="150.0"/>
  26. </bpmndi:BPMNShape>
  27. <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
  28. <omgdc:Bounds height="35.0" width="35.0" x="630.0" y="160.0"/>
  29. </bpmndi:BPMNShape>
  30. <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
  31. <omgdi:waypoint x="135.0" y="177.0"/>
  32. <omgdi:waypoint x="180.0" y="177.0"/>
  33. </bpmndi:BPMNEdge>
  34. <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
  35. <omgdi:waypoint x="285.0" y="177.0"/>
  36. <omgdi:waypoint x="330.0" y="177.0"/>
  37. </bpmndi:BPMNEdge>
  38. <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
  39. <omgdi:waypoint x="435.0" y="177.0"/>
  40. <omgdi:waypoint x="480.0" y="177.0"/>
  41. </bpmndi:BPMNEdge>
  42. <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
  43. <omgdi:waypoint x="585.0" y="177.0"/>
  44. <omgdi:waypoint x="630.0" y="177.0"/>
  45. </bpmndi:BPMNEdge>
  46. </bpmndi:BPMNPlane>
  47. </bpmndi:BPMNDiagram>
  48. </definitions>
  • .bpmn文件的根节点是definitions节点。这个元素中,可以定义多个流程定义(建议每个文件只包含一个流程定义,可以简化开发过程中的维护难度)。注意,definitions元素最少也要包含xmlns和targetNamespace的声明。targetNamespace可以是任何值,它用来对流程实例进行分类。
  • 流程定义部分:定义了流程每个结点的描述和结点之间的流程流转。
  • 流程布局定义:定义流程每个结点在流程图上的位置坐标等信息。

3.1.3 png图片文件

  • 如果是在Eclipse中,需要进行如下的配置:

Eclipse在保存bpmn文件的同时生成png图片.png

3.2 流程定义部署

3.2.1 什么是流程定义部署

  • 将生成的流程定义部署到Activiti的数据库中,这就是流程定义部署,通过调用Activiti的API将流程定义的bpmn和png两个文件一个一个添加部署到Activiti中,也可以将两个文件打成zip包进行部署。

3.2.2 单个文件部署方式

  • 分别将bpmn文件和png图片文件部署。
  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RepositoryService;
  5. import org.activiti.engine.repository.Deployment;
  6. import org.junit.Test;
  7. /**
  8. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  9. * @version 1.0
  10. * 2020-07-31 11:55
  11. */
  12. public class ActivitiDeploymentTest {
  13. /**
  14. * 部署流程定义:将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中
  15. *
  16. * act_re_deployment 部署信息
  17. * act_re_procdef 流程定义的一些信息
  18. * act_ge_bytearray 流程定义bpmn文件和png文件
  19. */
  20. @Test
  21. public void test() {
  22. //创建ProcessEngineConfiguration对象
  23. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  24. ProcessEngine processEngine = configuration.buildProcessEngine();
  25. //获取RepositoryService对象
  26. RepositoryService repositoryService = processEngine.getRepositoryService();
  27. //进行部署
  28. Deployment deployment = repositoryService.createDeployment()
  29. .addClasspathResource("diagram/holiday.bpmn") //添加bpmn资源
  30. .addClasspathResource("diagram/holiday.png")
  31. .name("请假申请流程")
  32. .deploy(); //部署
  33. //输出部署的一些信息
  34. String id = deployment.getId();
  35. System.out.println("流程部署id = " + id);
  36. String name = deployment.getName();
  37. System.out.println("流程部署名称 = " + name);
  38. }
  39. }

3.2.3 压缩包部署方式

  • 将.bpmn文件和.png图片压缩成一个zip包。

压缩包部署方式.png

  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RepositoryService;
  5. import org.activiti.engine.repository.Deployment;
  6. import org.junit.Test;
  7. import java.io.InputStream;
  8. import java.util.zip.ZipInputStream;
  9. /**
  10. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  11. * @version 1.0
  12. * 2020-07-31 11:55
  13. */
  14. public class ActivitiZipDeploymentTest {
  15. /**
  16. * 部署流程定义:将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中
  17. *
  18. * act_re_deployment 部署信息
  19. * act_re_procdef 流程定义的一些信息
  20. * act_ge_bytearray 流程定义bpmn文件和png文件
  21. */
  22. @Test
  23. public void test() {
  24. //创建ProcessEngineConfiguration对象
  25. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  26. ProcessEngine processEngine = configuration.buildProcessEngine();
  27. //获取RepositoryService对象
  28. RepositoryService repositoryService = processEngine.getRepositoryService();
  29. InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("diagram/holiday.zip");
  30. ZipInputStream zipInputStream = new ZipInputStream(inputStream);
  31. //进行部署
  32. Deployment deployment = repositoryService.createDeployment()
  33. .addZipInputStream(zipInputStream)
  34. .name("请假申请流程")
  35. .deploy(); //部署
  36. //输出部署的一些信息
  37. String id = deployment.getId();
  38. System.out.println("流程部署id = " + id);
  39. String name = deployment.getName();
  40. System.out.println("流程部署名称 = " + name);
  41. }
  42. }

3.2.4 操作数据表

  • 流程定义部署后,会操作三张表:act_re_deploymentact_re_procdefact_ge_bytearray
  • act_re_deployment是流程定义部署表,记录流程部署信息。
  • act_re_procdef是流程定义表,记录流程定义信息。
  • act_ge_bytearray是资源表,将.bpmn文件和.png图片存入到这个表。

说明:

  • act_re_deploymentact_re_procdef是一对多的关系,一次部署在流程部署表生成一条记录,但一次流程部署可以部署多个流程定义,每个流程定义在流程定义表生成一条记录。每一个流程定义在act_ge_bytearray会存在两个资源记录.bpmn文件和.png图片。

建议:

  • 一次部署一个流程,这样部署表和流程定义表示一对一的关系,方便读取流程部署和流程定义信息。

3.3 流程定义查询

  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RepositoryService;
  5. import org.activiti.engine.repository.ProcessDefinition;
  6. import org.activiti.engine.repository.ProcessDefinitionQuery;
  7. import org.junit.Test;
  8. import java.util.List;
  9. /**
  10. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  11. * @version 1.0
  12. * 2020-08-01 21:24
  13. */
  14. public class ActivitiProcessDefinitionQueryTest {
  15. /**
  16. * 查询流程定义信息
  17. */
  18. @Test
  19. public void test() {
  20. //创建ProcessEngineConfiguration对象
  21. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  22. ProcessEngine processEngine = configuration.buildProcessEngine();
  23. //获取RepositoryService对象
  24. RepositoryService repositoryService = processEngine.getRepositoryService();
  25. //得到ProcessDefinitionQuery对象
  26. ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
  27. //设置条件,并查询出当前的所有流程定义
  28. List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("holiday")
  29. .orderByProcessDefinitionVersion()
  30. .desc()
  31. .list();
  32. //输出流程定义信息
  33. for (ProcessDefinition processDefinition : processDefinitionList) {
  34. System.out.println("流程定义的id = " + processDefinition.getId());
  35. System.out.println("流程定义的name = " + processDefinition.getName());
  36. System.out.println("流程定义的key = " + processDefinition.getKey());
  37. System.out.println("流程定义的version = " + processDefinition.getVersion());
  38. }
  39. }
  40. }

3.4 流程定义删除

  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RepositoryService;
  5. import org.junit.Test;
  6. /**
  7. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  8. * @version 1.0
  9. * 2020-08-01 21:13
  10. */
  11. public class ActivitiDeleteProcessDefinitionTest {
  12. /**
  13. * 删除已经部署的流程定义
  14. *
  15. * 注意事项:
  16. * ①当我们正在执行的这一套流程没有结束,此时如果要删除流程定义信息就会失败(调用void deleteDeployment(String deploymentId)方法)。
  17. * ②当我们正在执行的这一套流程没有结束,此时如果要强制删除流程定义信息,需要调用void deleteDeployment(String deploymentId, boolean cascade)这个方式,将cascade设置为true。
  18. */
  19. @Test
  20. public void test() {
  21. //创建ProcessEngineConfiguration对象
  22. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  23. ProcessEngine processEngine = configuration.buildProcessEngine();
  24. //获取RepositoryService对象
  25. RepositoryService repositoryService = processEngine.getRepositoryService();
  26. //删除已经部署的流程定义
  27. String deploymentId = "1";
  28. repositoryService.deleteDeployment(deploymentId);
  29. }
  30. }

3.5 流程定义资源查询

  • 示例:通过查询流程定义对象获取流程定义资源,即bpmn和png
  1. package com.sunxiaping;
  2. import org.activiti.engine.ProcessEngine;
  3. import org.activiti.engine.ProcessEngineConfiguration;
  4. import org.activiti.engine.RepositoryService;
  5. import org.activiti.engine.repository.ProcessDefinition;
  6. import org.activiti.engine.repository.ProcessDefinitionQuery;
  7. import org.junit.Test;
  8. import org.springframework.util.FileCopyUtils;
  9. import java.io.File;
  10. import java.io.FileOutputStream;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.util.List;
  14. /**
  15. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  16. * @version 1.0
  17. * 2020-08-02 10:22
  18. */
  19. public class ActivitiResourceTest {
  20. @Test
  21. public void test() throws IOException {
  22. //创建ProcessEngineConfiguration对象
  23. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  24. ProcessEngine processEngine = configuration.buildProcessEngine();
  25. //获取RepositoryService对象
  26. RepositoryService repositoryService = processEngine.getRepositoryService();
  27. //获取ProcessDefinitionQuery对象
  28. ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
  29. //设置查询条件,执行查询操作
  30. List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list();
  31. //遍历查询结果
  32. for (ProcessDefinition processDefinition : processDefinitionList) {
  33. //获取资源名称,即png图片的名称
  34. String resourceName = processDefinition.getResourceName();
  35. //获取图表资源,即bpmn图片的名称
  36. String diagramResourceName = processDefinition.getDiagramResourceName();
  37. //获取资源的输入流,即png图片的输入流
  38. InputStream resourceNameInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
  39. InputStream diagramResourceNameInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), diagramResourceName);
  40. String resourcePath = "d:" + File.separator + resourceName;
  41. File file = new File(resourcePath);
  42. if (!file.exists()) {
  43. file.getParentFile().mkdirs();
  44. }
  45. String diagramResourcePath = "d:" + File.separator + diagramResourceName;
  46. file = new File(diagramResourcePath);
  47. if (!file.exists()) {
  48. file.getParentFile().mkdirs();
  49. }
  50. //复制文件
  51. FileCopyUtils.copy(resourceNameInputStream, new FileOutputStream(resourcePath));
  52. FileCopyUtils.copy(diagramResourceNameInputStream, new FileOutputStream(diagramResourcePath));
  53. }
  54. }
  55. }

3.6 流程历史信息查询

  • 示例:
  1. package com.sunxiaping;
  2. import org.activiti.engine.HistoryService;
  3. import org.activiti.engine.ProcessEngine;
  4. import org.activiti.engine.ProcessEngineConfiguration;
  5. import org.activiti.engine.history.HistoricActivityInstance;
  6. import org.activiti.engine.history.HistoricActivityInstanceQuery;
  7. import org.junit.Test;
  8. import java.util.List;
  9. /**
  10. * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
  11. * @version 1.0
  12. * 2020-08-01 21:13
  13. */
  14. public class ActivitiHistoryTest {
  15. @Test
  16. public void test() {
  17. //创建ProcessEngineConfiguration对象
  18. ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
  19. //获取ProcessEngine对象
  20. ProcessEngine processEngine = configuration.buildProcessEngine();
  21. //获取HistoryService对象
  22. HistoryService historyService = processEngine.getHistoryService();
  23. //获取HistoricActivityInstanceQuery查询对象
  24. HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
  25. List<HistoricActivityInstance> historicActivityInstanceList = historicActivityInstanceQuery.list();
  26. for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
  27. String activityId = historicActivityInstance.getActivityId();
  28. System.out.println("activityId = " + activityId);
  29. String activityName = historicActivityInstance.getActivityName();
  30. System.out.println("activityName = " + activityName);
  31. String processDefinitionId = historicActivityInstance.getProcessDefinitionId();
  32. System.out.println("processDefinitionId = " + processDefinitionId);
  33. String processInstanceId = historicActivityInstance.getProcessInstanceId();
  34. System.out.println("processInstanceId = " + processInstanceId);
  35. }
  36. }
  37. }