• Activiti审批流


    名词解释

    转办:某个节点,候选人是好几人。其中一个人拾取了该任务,发现不应该办理,可以转给候选人中的其他人

    会签:

    1 bpmn

    StartEvent开始事件(重要)
    EndEvent结束事件(重要)
    IntermediateEvent中间事件
    UserTask用户任务:表示需要人参与的任务,可以配置候选人/组/代理人等。(重要)
    ServiceTask服务任务:调用外部服务或自动执行程序。
    ManualTask手工任务:就是一个直接通过的任务。可以使用它来自动执行一些可以直接通过的任务
    BusinessRuleTask规则任务:
    SubProcess子流程:子流程表示多个activity的组合。子流程内部的元件禁止和外部的元件直连,只能作为一个整体与父流程的元件相连接。
    Lane
    ExclusiveGateway排他网关
    EventGateway
    IntermediateCatchingEvent
    Annotation
    ScriptTask脚本任务:用于执行定义好的脚本程序,流程执行到这个结点自动执行脚本。
    MailTask        
    ReceiveTask
       CallActivityTask    
    Pool
    ParallelGateway并行网关
    InclusiveGateway包容性网关
       BoundaryEvent    
    IntermediateThrowingEvent

    BPMN2.0之顺序流和网关_Richard678的博客-CSDN博客_bpmn顺序

    https://www.jianshu.com/p/6f38a0275e98/

    userTask属性:

    documentation文档
    asynchronous异步
    exclusive独家专用的
    multi instance多实例
    assignee代理人,受让人
    candidate users候选人 ; 申请人
    candidate groups候选组
    due date到期日
    form key表单键
    priority优先事项
    task listeners任务监听器
    execution listeners执行监听器
    form表单

    2 Activiti表

    表分类表名
    一般数据
    act_ge_bytearray通用的流程定义和流程资源
    act_ge_property系统相关属性
    流程历史记录
    act_hi_actinst历史的流程实例 (节点表,审批到哪个节点了,)
    act_hi_attachment历史的流程附件
    act_hi_comment历史的流程说明性信息
    act_hi_detail历史的流程运行中的细节信息
    act_hi_identitylink历史的流程运行过程中用户关系
    act_hi_procinst历史的流程实例
    act_hi_taskinst历史的任务实例
    act_hi_varinst历史的流程运行中的变量信息
    流程定义表
    act_re_deployment部署单元信息
    act_re_model模型信息
    act_re_procdef部署的流程定义
    运行实例表
    act_ru_deadletter_job死信
    act_ru_event_subscr运行时事件
    act_ru_execution运行时流程执行实例
    act_ru_identitylink运行时用户关系信息,存储任务节点与参与者的相关信息
    act_ru_integration集成
    act_ru_job运行时作业
    act_ru_suspended_job暂停
    act_ru_task运行时任务
    act_ru_timer_job
    act_ru_variable运行时变量表
    1. Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
    2. ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
    3. ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
    4. ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
    5. ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
    6. ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

    activiti7和activiti6的区别:

    不同点:activiti6是28张数据表,activiti7是25张,少了用户和组的三张表。相应的服务接口也少了俩:IdentityService和FormService。另外activiti7中对activiti6的API再次进行了封装,新增加了分布式和云部署的功能,核心没变

    RepositoryService:流程定义和部署对象
    RuntimeService:执行管理,包括流程实例和执行对象(正在执行)
    TaskService:执行任务相关的(正在执行)
    HistoryService:历史管理
    IdentityService:Activiti表的用户角色组
    ManagementService:引擎管理服务

     

     

     

    activiti开发工作流的一个基本开发模式

    功能复用:对于像查询待办任务、已办任务、抄送我的、我发起的流程、流程部署、流程挂起与激活、生成流程图等这样的可以复用的功能,使用一套代码即可,提供统一的接口或service。

    功能不复用:但是对于启动流程、完成任务这样的功能,因为每个流程的参数或流程变量不一样,并且任务完成之后做的回调事情也不一样,如果不能复用,则每一个流程都单独开发这样的功能。
     

    目前采用的方式是:对于启动流程、完成任务抽象出一个interface,让不同的流程service实现各自不同的操作;创建一个简单工厂,根据流程类型实例化不同的流程service;对外只暴露出启动流程和完成任务两个接口,前端传递不同的流程类型,执行不同的service操作。

    数据表扩展:如果activiti提供的数据表无法满足业务需求,可以建立关联表,辅助业务运行。

    3 开发准备

    idea插件actiBPM 和pom

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-web</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>org.mybatis.spring.boot</groupId>
    7. <artifactId>mybatis-spring-boot-starter</artifactId>
    8. <version>2.2.2</version>
    9. </dependency>
    10. <dependency>
    11. <groupId>com.alibaba</groupId>
    12. <artifactId>druid-spring-boot-starter</artifactId>
    13. <version>1.1.10</version>
    14. </dependency>
    15. <dependency>
    16. <groupId>mysql</groupId>
    17. <artifactId>mysql-connector-java</artifactId>
    18. <scope>runtime</scope>
    19. <!-- <version>8.0.30</version>-->
    20. </dependency>
    21. <dependency>
    22. <groupId>org.projectlombok</groupId>
    23. <artifactId>lombok</artifactId>
    24. <optional>true</optional>
    25. </dependency>
    26. <dependency>
    27. <groupId>org.springframework.boot</groupId>
    28. <artifactId>spring-boot-starter-test</artifactId>
    29. <scope>test</scope>
    30. </dependency>
    31. <!-- <dependency>
    32. <groupId>org.activiti</groupId>
    33. <artifactId>activiti-bpmn-converter</artifactId>
    34. <version>6.0.0</version>
    35. </dependency>-->
    36. <!--
    37. <dependency>
    38. <groupId>org.activiti</groupId>
    39. <artifactId>activiti-engine</artifactId>
    40. <version>7.0.0.Betal</version>
    41. </dependency>
    42. <dependency>
    43. <groupId>org.activiti</groupId>
    44. <artifactId>activiti-spring</artifactId>
    45. <version>7.0.0.Betal</version>
    46. </dependency>
    47. &lt;!&ndash; bpmn模型处理&ndash;&gt;
    48. <dependency>
    49. <groupId>org.activiti</groupId>
    50. <artifactId>activiti-bpmn-model</artifactId>
    51. <version>7.0.0.Betal</version>
    52. </dependency>
    53. &lt;!&ndash; bpmn转换&ndash;&gt;
    54. <dependency>
    55. <groupId>org.activiti</groupId>
    56. <artifactId>activiti-bpmn-converter</artifactId>
    57. <version>7.0.0.Betal</version>
    58. </dependency>
    59. &lt;!&ndash; bpmn json数据转换&ndash;&gt;
    60. <dependency>
    61. <groupId>org.activiti</groupId>
    62. <artifactId>activiti-json-converter</artifactId>
    63. <version>7.0.0.Betal</version>
    64. </dependency>
    65. &lt;!&ndash; bpmn 布局&ndash;&gt;
    66. <dependency>
    67. <groupId>org.activiti</groupId>
    68. <artifactId>activiti-bpmn-layout</artifactId>
    69. <version>7.0.0.Betal</version>
    70. </dependency>
    71. &lt;!&ndash; activiti 云支持&ndash;&gt;
    72. <dependency>
    73. <groupId>org.activiti.cloud</groupId>
    74. <artifactId>activiti-cloud-service-api</artifactId>
    75. <version>7.0.0.Betal</version>
    76. </dependency>
    77. -->
    78. <dependency>
    79. <groupId>org.slf4j</groupId>
    80. <artifactId>slf4j-log4j12</artifactId>
    81. <version>1.6.6</version>
    82. </dependency>
    83. <dependency>
    84. <groupId>log4j</groupId>
    85. <artifactId>log4j</artifactId>
    86. <version>1.2.12</version>
    87. </dependency>
    88. <dependency>
    89. <groupId>org.activiti</groupId>
    90. <artifactId>activiti-spring-boot-starter</artifactId>
    91. <version>7.0.0.Beta2</version>
    92. </dependency>
    93. <dependency>
    94. <groupId>commons-io</groupId>
    95. <artifactId>commons-io</artifactId>
    96. <version>2.6</version>
    97. </dependency>

     yml

    1. server:
    2. port: 8080
    3. spring:
    4. application:
    5. name: activiti
    6. datasource:
    7. driver-class-name: com.mysql.jdbc.Driver
    8. url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=UTF-8&useTimezone=true&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true
    9. username: root
    10. password: root
    11. druid:
    12. filter:
    13. stat:
    14. enabled: true
    15. db-type: mysql
    16. log-slow-sql: true
    17. activiti:
    18. # false:默认值。在activiti启动时,会对比数据库表中保存的版本,如果没有表或版本不匹配,将抛出异常。(生产环境常用)
    19. # true:activiti会对数据库中所有表进行更新操作。如果表不存在,将会创建。(开发环境常用)
    20. # create-drop:在activiti启动时创建表,在关闭时删除表,必须手动关闭引擎才会删除表。(单元测试用)
    21. # drop-create:在activiti启动时删除旧表,然后创建新表,不需要关闭引擎。
    22. database-schema-update: true
    23. #检测历史表是否存在,activiti7默认没有开启数据库历史记录,true启动数据库历史记录
    24. db-history-used: true
    25. #记录历史等级,可配置的历史级别有:none,activity,audit,full
    26. # none:不保存任何的历史数据,因此在流程执行过程中,这是最高效的
    27. # activity:级别高于none,保存流程实例与流程行为,其他数据不保存
    28. # audit:除保存activity保存的数据外,还会保存全部的流程任务及其属性。history-level的默认值
    29. # full:保存历史数据的最高级别,会额外保存全部流程相关的细节数据。
    30. history-level: full
    31. #校验流程文件,默认校验resources下的process文件夹的流程文件
    32. check-process-definitions: false
    33. logging:
    34. pattern:
    35. console: "%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n"
    36. level:
    37. org.activiti.engine.impl.persistence.entity: trace
    38. mybatis:
    39. configuration:
    40. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    资源文件下加配置文件activiti.cfg.xml和log4j.properties文件

     activiti.cfg.xml:springboot方式就不用了。

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <!--dbcp数据源-->
    6. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    7. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    8. <property name="url" value="jdbc:mysql://localhost:3306/activiti"/>
    9. <property name="username" value="root"/>
    10. <property name="password" value="root"/>
    11. </bean>
    12. <!--配置Activiti的ProcessEngineConfiguration对象,因为没有跟spring整合,所以这里使用单例的。-->
    13. <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    14. <!--注入数据源-->
    15. <property name="dataSource" ref="dataSource"/>
    16. <!--指定数据表生成策略,该策略是,若数据表不存在则创建,存在则更新-->
    17. <property name="databaseSchemaUpdate" value="true"/>
    18. </bean>
    19. </beans>

    代码实战

    Activiti学习——踩坑和经验_chuchui5713的博客-CSDN博客

    分配个人任务的三种方式
    1:直接给值,在Xxxx.bpmn文件中指定
    2:流程变量${流程变量的名称}或者#{}
    3:使用类 监听这个类(实现一个接口),指定任务的办理人(setAssgnee())

    个人任务和组任务的查询一样吗?
    * 不一样
    * 都是用TaskService完成(TaskService.createTasQuery)
    * 个人任务(taskAssgnee),组任务(taskCandidateUser)
    * 数据库存放,个人任务(类型:参与),组任务(类型,参与,候选)
     

    bpmn创建一个简单请假流程

    张三提交申请单---> 李四经理审批--->王五总经理审批

    生成图片流程:

     1将travel.bpmn 改名为 travel.xml

    2:右击 找到Diagrams --->show BPMN 2.0 Designer

    3: 点击导出 image

    4 将 travel.xml改为 travel.bpmn

     

    结论:

      act_re_deployment (流程部署 )和act_re_procdef(流程定义) 一对多的关系

       procdef表中,可以有多条记录,每一条记录,对应一个流程的定义信息。

       张三 走这个出差申请流程

       李四 也走这个出差申请流程

    简单的案例代码

    1. package com.example.activiti;
    2. import org.activiti.engine.*;
    3. import org.activiti.engine.history.HistoricActivityInstance;
    4. import org.activiti.engine.history.HistoricActivityInstanceQuery;
    5. import org.activiti.engine.repository.Deployment;
    6. import org.activiti.engine.repository.ProcessDefinition;
    7. import org.activiti.engine.repository.ProcessDefinitionQuery;
    8. import org.activiti.engine.runtime.ProcessInstance;
    9. import org.activiti.engine.task.Task;
    10. import org.activiti.engine.task.TaskQuery;
    11. import org.apache.commons.io.IOUtils;
    12. import org.junit.jupiter.api.BeforeEach;
    13. import org.junit.jupiter.api.Test;
    14. import org.springframework.boot.test.context.SpringBootTest;
    15. import java.io.File;
    16. import java.io.FileOutputStream;
    17. import java.io.IOException;
    18. import java.io.InputStream;
    19. import java.util.List;
    20. import java.util.zip.ZipInputStream;
    21. @SpringBootTest
    22. class ActivitiApplicationTests {
    23. static ProcessEngine processEngine = null;
    24. @BeforeEach
    25. void test() {
    26. /**
    27. * 初始化流程引擎对象,将会根据配置创建25数据表(创建了索引和外键)
    28. */
    29. processEngine = ProcessEngines.getDefaultProcessEngine();
    30. }
    31. /**
    32. * 部署流程 将流程保存到数据中
    33. */
    34. @Test
    35. void test1() {
    36. RepositoryService repositoryService = processEngine.getRepositoryService();
    37. //zip方式部署 (可以很多流程都压缩在一个zip下)
    38. InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/travel.zip");
    39. ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    40. Deployment deploy = repositoryService.createDeployment().addZipInputStream(zipInputStream)
    41. // .name("")
    42. .deploy();
    43. // 单个部署方式
    44. Deployment deployment = repositoryService.createDeployment()
    45. .addClasspathResource("bpmn/travel.bpmn")
    46. .addClasspathResource("bpmn/travel.png")
    47. // .name("请假流程测试")
    48. // .category("办公类别") //设置部署的类别
    49. .deploy();
    50. System.out.println(deployment.getId());//流程部署id 6f2030ef-58ec-11ed-bbe8-fa89d281dc2b
    51. System.out.println(deployment.getName());//流程部署名字 请假流程测试
    52. System.out.println(deployment.getKey());//null
    53. System.out.println(deployment.getCategory());//null
    54. System.out.println(deployment.getDeploymentTime());
    55. System.out.println(deployment.getTenantId());//null
    56. /*
    57. 受影响的表:3
    58. act_re_deployment:流程部署表 : 添加一条流程部署记录 主键是贯穿这三个表
    59. act_re_procdef::流程定义:添加一条流程定义记录,一个流程定义记录和一个流程图一一对应,流程定义记录的key就是流程图的id
    60. act_ge_bytearray:blob形式保存部署的资源
    61. */
    62. /*
    63. 流程部署意味着两件事:
    64. 1、将流程定义文件放到activiti引擎配置的持久化存储中,以便activiti引擎重启时能再次读取部署的流程。
    65. 2、解析bpmn文件并转化为activiti内存中的对象模型,然后就能使用acticiti提供的api对持久化的数据进行操作。
    66. */
    67. }
    68. /**
    69. * 查询流程定义 act_re_procdef
    70. */
    71. @Test
    72. void tes2() {
    73. RepositoryService repositoryService = processEngine.getRepositoryService();
    74. ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    75. List<ProcessDefinition> myTravel_1 = processDefinitionQuery.processDefinitionKey("myTravel_1")
    76. .orderByProcessDefinitionVersion() //根据 Version 正序
    77. .asc() //正序
    78. .list();
    79. for (ProcessDefinition processDefinition : myTravel_1) {
    80. System.out.println("流程定义ID: "+processDefinition.getId());//IDmyTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b
    81. System.out.println("流程定义名称: "+processDefinition.getName()); //出差申请流程
    82. System.out.println("流程定义key: "+processDefinition.getKey()); //keymyTravel_1
    83. System.out.println("流程定义版本: "+processDefinition.getVersion()); //1
    84. System.out.println("流程定义部署id: "+processDefinition.getDeploymentId()); //710668f8-5904-11ed-b08d-fa89d281dc2b
    85. }
    86. }
    87. /**
    88. * 删除流程定义 act_re_procdef
    89. */
    90. @Test
    91. void tes3() {
    92. RepositoryService repositoryService = processEngine.getRepositoryService();
    93. //通过部署id删除流程部署信息 不会删除历史表的信息
    94. repositoryService.deleteDeployment("54215d66-5903-11ed-a890-fa89d281dc2b");
    95. //历史信息也会删除
    96. repositoryService.deleteDeployment("54215d66-5903-11ed-a890-fa89d281dc2b",true);
    97. /**
    98. * delete from ACT_GE_BYTEARRAY where DEPLOYMENT_ID_ =
    99. * delete from ACT_RE_DEPLOYMENT where ID_ =
    100. * delete from ACT_RE_PROCDEF where DEPLOYMENT_ID_ =
    101. * delete from ACT_RU_IDENTITYLINK where PROC_DEF_ID_ =
    102. */
    103. }
    104. /**
    105. * 下载流程
    106. */
    107. @Test
    108. void tes4() throws IOException {
    109. RepositoryService repositoryService = processEngine.getRepositoryService();
    110. //查询流程定义信息
    111. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
    112. .processDefinitionKey("myTravel_1").singleResult();
    113. //获取流程部署id
    114. String deploymentId = processDefinition.getDeploymentId();
    115. //获取图片目录和名字
    116. String pngName = processDefinition.getDiagramResourceName();
    117. InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
    118. //获取bpmn目录和名字
    119. String bpmnName = processDefinition.getResourceName();
    120. InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);
    121. File pngfile = new File("D:/travel.png");
    122. File bpmnfile = new File("D:/travel.bpmn");
    123. FileOutputStream pngOutputStream = new FileOutputStream(pngfile);
    124. FileOutputStream bpmnOutputStream = new FileOutputStream(bpmnfile);
    125. IOUtils.copy(pngInput, pngOutputStream);
    126. IOUtils.copy(bpmnInput, bpmnOutputStream);
    127. pngInput.close();
    128. bpmnInput.close();
    129. pngOutputStream.close();
    130. bpmnOutputStream.close();
    131. }
    132. /**
    133. * 运行工作流
    134. */
    135. @Test
    136. void test5() {
    137. RuntimeService runtimeService = processEngine.getRuntimeService();
    138. //act_re_procdef---拿来的参数
    139. ProcessInstance processInstance = runtimeService.startProcessInstanceById("myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b");
    140. // runtimeService.startProcessInstanceByKey("myTravel_1");
    141. System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b
    142. System.out.println("流程实例ID"+processInstance.getId());//c96e78ef-58f7-11ed-9f8b-fa89d281dc2b
    143. System.out.println("流程活动ID"+processInstance.getActivityId());//null
    144. /* act_ru_task 任务信息
    145. * act_ru_identitylink 标识链接 流程的参与用户信息
    146. * act_ru_execution 处决 流程正在执行信息
    147. * act_hi_taskinst 任务 流程任务历史信息
    148. * act_hi_procinst 流程实例历史信息
    149. * act_hi_identitylink 流程的参与用户信息历史
    150. * act_hi_actinst 流程实例执行历史
    151. *
    152. * */
    153. }
    154. /**
    155. * 查询张三正在执行任务查询
    156. * 正在执行的任务会在这个表 ACT_RU_TASK ,一旦这个节点完成,会到历史表中,下一个节点到 ACT_RU_TASK 中
    157. * https://blog.csdn.net/JHC23/article/details/97001687?ops_request_misc=&request_id=&biz_id=102&utm_term=activi&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-5-97001687.142^v62^pc_search_tree,201^v3^control_1,213^v1^control&spm=1018.2226.3001.4187
    158. */
    159. @Test
    160. void test6() {
    161. TaskService taskService = processEngine.getTaskService();
    162. //创建任务查询对象
    163. TaskQuery taskQuery = taskService.createTaskQuery();
    164. //查看办理人的任务列表
    165. List<Task> list = taskQuery
    166. .processDefinitionKey("myTravel_1") // 流程key
    167. .taskAssignee("张三").list();//要查询的负责人
    168. //select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ ="张三"
    169. // select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = '张三' and D.KEY_ = 'myTravel_1'
    170. for (Task task : list) {
    171. System.out.println("任务办理人:"+task.getAssignee());
    172. System.out.println("任务id:" + task.getId());
    173. System.out.println("任务名称:"+ task.getName());
    174. System.out.println("流程实例id:"+ task.getProcessInstanceId());
    175. }
    176. }
    177. /**
    178. * 张三提交申请单 完成个人任务
    179. */
    180. @Test
    181. void test7() {
    182. TaskService taskService = processEngine.getTaskService();
    183. //根据任务id act_ru_task 表的 id 完成任务
    184. // act_ru_task 目前节点是 提交申请单
    185. taskService.complete("75b2666e-598d-11ed-951f-fa89d281dc2b");
    186. // 执行后 act_ru_task 节点变成 经理审批 act_hi_taskinst 也会多一个经理审批
    187. /*流程sql
    188. select * from ACT_RU_TASK where ID_ = 'c972e5c3-58f7-11ed-9f8b-fa89d281dc2b'
    189. * select * from ACT_RE_PROCDEF where ID_ = 'myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b'
    190. * select * from ACT_RE_DEPLOYMENT where ID_ ='6f2030ef-58ec-11ed-bbe8-fa89d281dc2b'
    191. * select * from ACT_GE_BYTEARRAY where DEPLOYMENT_ID_ = '6f2030ef-58ec-11ed-bbe8-fa89d281dc2b' order by NAME_ asc
    192. * insert into ACT_HI_TASKINST 经理审批的数据
    193. * insert into ACT_HI_ACTINST 经理审批的数据
    194. * insert into ACT_HI_IDENTITYLINK 李四人员数据
    195. insert into ACT_RU_TASK 经理审批的数据
    196. insert into ACT_RU_IDENTITYLINK 李四人员数据
    197. * update ACT_HI_ACTINST 张三
    198. update ACT_RU_EXECUTION update ACT_HI_TASKINST delete from ACT_RU_TASK 张三
    199. */
    200. }
    201. /**
    202. * 查看历史信息 (审批节点) ACT_HI_ACTINST
    203. */
    204. @Test
    205. void test8() {
    206. HistoryService historyService = processEngine.getHistoryService();
    207. HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
    208. //act_hi_actinst表 PROC_INST_ID_字段
    209. //select RES.* from ACT_HI_ACTINST RES WHERE RES.PROC_INST_ID_ = ?
    210. instanceQuery.processInstanceId("c96e78ef-58f7-11ed-9f8b-fa89d281dc2b");
    211. //排序 开始
    212. instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
    213. List<HistoricActivityInstance> list = instanceQuery.list();
    214. for (HistoricActivityInstance instance : list) {
    215. System.out.println(instance.getActivityId());//_3
    216. System.out.println(instance.getActivityName());// 经理审批
    217. System.out.println(instance.getProcessDefinitionId()); //myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b
    218. System.out.println(instance.getProcessInstanceId());//c96e78ef-58f7-11ed-9f8b-fa89d281dc2b
    219. }
    220. }
    221. @Test
    222. void del() {
    223. RepositoryService repositoryService = processEngine.getRepositoryService();
    224. // repositoryService.deleteDeployment();
    225. RuntimeService runtimeService = processEngine.getRuntimeService();
    226. //act_re_procdef---拿来的参数
    227. // ProcessInstance processInstance = runtimeService.startProcessInstanceById("myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b");
    228. runtimeService.deleteProcessInstance("51b423d0-5902-11ed-b595-fa89d281dc2b","");
    229. }
    230. }

    晋级版

    绑定其他业务表

      占位符方式

    UEL-value方式:    ${submitName}  

    UEL-method方式: ${User.submitName}

    结合版: ${userService.findUser(userBean)}

       详解:userService是spring容器的类,调用接口 findUser 入参 userBean 是activiti流程变量

    其他:${order.price>100 && order.price<200}  表达式支持解析基础类型,bean,list,array,map

    1. static ProcessEngine processEngine = null;
    2. @BeforeEach
    3. void test() {
    4. /**
    5. * 初始化流程引擎对象,将会根据配置创建25数据表(创建了索引和外键)
    6. */
    7. processEngine = ProcessEngines.getDefaultProcessEngine();
    8. }
    9. /**
    10. * 分配任务负责人
    11. * 1:固定方式
    12. * 2 uel表达式方式 ( UEL-value 和 UEL-method)
    13. * 3 监听器方式
    14. */
    15. @Test
    16. void test4() {
    17. // 1:固定方式 就是我们用idea软件画图的时候直接给死了人员名称。创建申请单就是张三。
    18. /* 注意一定变成xml方式看看是不是写的表达式,有的时候变不过来
    19. 2: UEL-value方式: ${submitName}
    20. UEL-method方式: ${User.submitName}
    21. 结合版: ${userService.findUser(userBean)} userService是spring容器的类,调用接口 findUser 入参 userBean 是activiti流程变量
    22. 其他:${order.price>100 && order.price<200} 表达式支持解析基础类型,bean,list,array,map
    23. */
    24. RepositoryService repositoryService = processEngine.getRepositoryService();
    25. Deployment deployment = repositoryService.createDeployment()
    26. .addClasspathResource("bpmn/travel3.bpmn")
    27. .name("动态人员出差申请流程")
    28. .deploy();
    29. RuntimeService runtimeService = processEngine.getRuntimeService();
    30. HashMap<String, Object> hashMap = new HashMap<>();
    31. hashMap.put("submitName","张三-动态");
    32. hashMap.put("approval1","李四-动态");
    33. hashMap.put("approval2","王五-动态");
    34. runtimeService.startProcessInstanceByKey("myTravel_3",hashMap);
    35. // act_ru_variable 会存 字段和人名 映射关系
    36. // 删除 repositoryService.deleteDeployment("240b39a6-59c8-11ed-8bd7-fa89d281dc2b",true);
    37. }

     挂起

    1. /**
    2. * 挂起:当流程实例没有跑完,如果已经挂起,就不能继续处理了,只有当流程激活后,才能继续执行。
    3. * 挂起后 完成任务 taskService.complete() 报错会
    4. * act_ru_task:SUSPENSION_STATE_ 暂停_状态_ 1 未暂停 2 暂停
    5. */
    6. @Test
    7. void test3() {
    8. /**
    9. * 多实例流程的挂起
    10. */
    11. RepositoryService repositoryService = processEngine.getRepositoryService();
    12. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myTravel_1").singleResult();
    13. //当前所有流程实例是否被挂起
    14. boolean suspended = processDefinition.isSuspended();
    15. if(suspended){
    16. //激活方法 参数1:流程定义id 参数2:是否激活 参数3:激活时间
    17. repositoryService.activateProcessDefinitionById(processDefinition.getId(),true,null);
    18. }else {
    19. //挂起方法 参数1:流程定义id 参数2:是否暂停 参数3:暂停时间
    20. repositoryService.suspendProcessDefinitionById(processDefinition.getId(),true,null);
    21. }
    22. /**
    23. * 单个流程实例的挂起
    24. */
    25. RuntimeService runtimeService = processEngine.getRuntimeService();
    26. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processDefinitionId("c96e78ef-58f7-11ed-9f8b-fa89d281dc2b").singleResult();
    27. boolean suspended1 = processInstance.isSuspended();
    28. if(suspended1){
    29. //激活方法 参数1:流程定义id
    30. runtimeService.activateProcessInstanceById(processInstance.getId());
    31. }else {
    32. //挂起方法
    33. runtimeService.suspendProcessInstanceById(processInstance.getId());
    34. }
    35. }

    监听器方式 动态分配人员 我的插件不好使了。始终出不来 算了

     使用global变量控制流程

     员工创建出差申请单,由经理审核,经理审核通过后出差3天一下直接由财务审批,3天以上由总经理审批,在财务审核。

     

    1. static ProcessEngine processEngine = null;
    2. @BeforeEach
    3. void test() {
    4. /**
    5. * 初始化流程引擎对象,将会根据配置创建25数据表(创建了索引和外键)
    6. */
    7. processEngine = ProcessEngines.getDefaultProcessEngine();
    8. }
    9. /**
    10. * 使用global变量控制流程
    11. */
    12. @Test
    13. void test6() {
    14. //保存到数据库
    15. RepositoryService repositoryService = processEngine.getRepositoryService();
    16. Deployment deployment = repositoryService.createDeployment()
    17. .addClasspathResource("bpmn/evection-global.bpmn")
    18. .name("global变量动态人员出差申请流程")
    19. .deploy();
    20. //开启流程
    21. RuntimeService runtimeService = processEngine.getRuntimeService();
    22. HashMap<String, Object> hashMap = new HashMap<>();
    23. Evection evection = new Evection();
    24. evection.setNum(2.0);
    25. evection.setId(1L);
    26. evection.setReason("项目出差原因");
    27. hashMap.put("evection",evection);
    28. hashMap.put("submitName","张三提交");
    29. hashMap.put("approval1","李四经理审批");
    30. hashMap.put("approval2","王五总经理-动态");
    31. hashMap.put("approval3","李六财务-动态");
    32. runtimeService.startProcessInstanceByKey("evection-global",hashMap);
    33. }

    组任务

    就是给当前流程设置多个负责人。

     

    多人审批该任务时候。不能立即审批。先看这个人是不是候选人之一,是的话,还要在拾取该任务,变成个人任务。才能办理。

    如果不想办理,还要将任务还回去。

    1. /**
    2. * 组任务 74
    3. */
    4. @Test
    5. void test7() {
    6. //保存到数据库
    7. RepositoryService repositoryService = processEngine.getRepositoryService();
    8. Deployment deployment = repositoryService.createDeployment()
    9. .addClasspathResource("bpmn/travel-candidate.bpmn")
    10. .name("组人员出差申请流程")
    11. .deploy();
    12. //流程定义的key
    13. String key="travel-candidate";
    14. //开启流程
    15. RuntimeService runtimeService = processEngine.getRuntimeService();
    16. runtimeService.startProcessInstanceByKey(key);
    17. TaskService taskService = processEngine.getTaskService();
    18. //创建申请单(张三) ----->经理审批(候选人 wangwu和lisi)-------等等
    19. String userId="张三";
    20. //创建申请单步骤
    21. // 张三查询自己待办任务
    22. Task task1 = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(userId).singleResult();
    23. if(task1!=null){
    24. //完成任务
    25. taskService.complete(task1.getId());
    26. }
    27. //经理审批 (组任务模式 候选人 wangwu和lisi)
    28. String candidateUserId="wangwu";
    29. //查询这个候选人待办任务
    30. Task task3 = taskService.createTaskQuery().processDefinitionKey(key)
    31. .taskCandidateUser(candidateUserId) //候选人
    32. //.list() 查询所有待办
    33. .singleResult();
    34. System.out.println("任务id"+task3.getId());
    35. System.out.println("任务负责人"+task3.getAssignee()); //null 因为还没有人拾取任务
    36. if(task3!=null){
    37. //拾取该任务
    38. taskService.claim(task3.getId(),candidateUserId);
    39. }
    40. //拾取完可以办理或归还任务
    41. // taskService.complete(task3.getId()); 完成任务
    42. //归还任务
    43. taskService.setAssignee(task3.getId(),null); //归还任务就是把负责人设置为null
    44. // 任务的转办(任务交接) :这个任务我做不了,想交给别人做。
    45. // 候选人王五做不了,转给李四做
    46. taskService.setAssignee(task3.getId(),"lisi"); //转办任务就是把负责人设置为目标人
    47. }

    网关

    排他网关

     排他网关exclusiveGateway: 排他网关只会选择一个为true去执行。都为true 选择id值较小的那条线去执行。
      (global变量控制流程)连线上设置分支条件方式:  不符合任何一条条件时,会结束任务
      排他网关方式:                              不符合任何一条条件时,会抛异常。扔我们知道哪出问题了。

    并行网关

    拆分:拆分处,有几个分支就会走几个分支,不会因为连线处有条件而不执行。

    聚合:等所有分支都执行完,才能继续往下走。

     

     

  • 相关阅读:
    linux查看系统信息
    Abnova丨培养细胞总 RNA 纯化试剂盒中英文说明书
    递增序列主题Code
    数据结构:线段树(SegNode)
    这才叫高并发,阿里架构师手写的三份绝密百亿级架构笔记限时分享
    HTML静态网页成品作业(HTML+CSS)——电影网首页网页设计制作(1个页面)
    含文档+PPT+源码等]计算机毕业设计微信小程序开发项目源代码家庭理财系统+后台管理系统|前后分离VUE[包运行成功]
    超图平台(工作空间,数据源,数据集,记录集的使用)
    记录一次手动读取BigTiff文件(Python)
    Js内存泄漏情况解析
  • 原文地址:https://blog.csdn.net/weixin_44383484/article/details/127555360