文章目录
- Activiti官网
 - 一、BPM
 - 二、BPM软件
 - 三、BPMN
 - 四、Activiti使用步骤
 - 1、部署activiti
 - 2、流程定义
 - 3、流程定义部署
 - 4、启动一个流程实例
 - 5、用户查询待办任务(Task)
 - 6、用户办理任务
 - 7、流程结束
 
- 五、Activiti环境准备
 - 1、下载扩展程序camunda-modeler
 - 2、配置idea扩展程序:
 
- 六、Activiti数据库支持
 - 1、Activiti支持的数据库
 - 2、MySQL生成表
 - 1)创建数据库activiti
 - 2)pom依赖
 - 3)log4j.properties
 - 4)activiti.cfg.xml
 - 5)生成Activiti表
 
- 3、表结构认识
 
- 七、Activiti使用入门案例
 - 1、创建流程定义
 - 2、部署流程定义
 - 1)方式1——文件上传
 - 2)方 式2——压缩文件上传
 
- 3、启动流程实例
 - 4、查询任务
 - 5、流程任务处理
 - 6、流程是心查询
 - 7、删除流程
 - 8、流程资源下载
 - 9、流程历史信息查看
 
- 八、Activiti进阶
 - 1、 流程定义与流程实例定义
 - 1)启动流程实例时添加Businesskey
 - 2)挂起流程&激活流程
 
- 2、流程变量
 - 1) 流程变量的作用域
 - 2)使用流程变量
 - 3)设置全局Global流程变量
 - ①启动流程时设置变量
 - ②任务办理时设置变量
 - ③通过当前流程实例设置变量
 - ④通过当前任务设置变量
 
- 4)设置Local流程变量
 
- 3、网关
 - 1) 排他网关ExclusiveGateway
 - 2) 并行网关ParallelGateway
 - 3) 包含网关InclusiveGateway
 - 4) 事件网关EventGatway
 
- 4、个人任务管理
 - 5、组任务分配
 - 1)设置多个候选人
 - 2)组任务办理流程
 
- 九、Activiti与Spring整合
 - 十、Activiti7与SpringBoot整合
 - 1、pom
 - 2、application.yml
 - 3、启动类
 - 4、SpringSecurityConfig
 - 5、工具类
 
Activiti官网
一、BPM
BPM(Business Process Management),即业务流程管理,是一种规范化的构造端到端的业务流程,以持续的提高组织业务效率。常见商业管理教育如EMBA、MBA等均将BPM包含在内。
二、BPM软件
BPM软件就是根据企业中业务环境的变化,推进人与人之间、人与系统之间以及系统与系统之间的整合及调整的经营方法与解决方案的IT工具。
 通过BPM软件对企业内部及外部的业务流程的整个生命周期进行建模、自动化、管理监控和优化,使企业成本降低,利润得以大幅提升。
 BPM软件在企业中应用领域广泛,凡是有业务流程的地方都可以BPM软件进行管理,比如企业人事办公管理、采购流程管理、公文审批流程管理、财务管理等。
三、BPMN
BPMN(BusinessProcessModelAndNotation)-业务流程模型和符号是由BPMI(BusinessProcess ManagementInitiative)开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。
2004年5日发布了BPMN1.0规范.BPMI于2005年9月并入OMG(The Obiect Management Groun对象管理组织
 组织。OMG于2011年1月发布BPMN2.0的最终版本。
BPMN 是目前被各 BPM 厂商广泛接受的 BPM 标准。Activiti 就是使用 BPMN 2.0 进行流程建模、流程执行管理。它包括很多的建模符号,比如:
 Event用一个圆圈表示,它是流程中运行过程中发生的事情。
 流程开始,流程结束。。。
 
 活动用圆角矩形表示,一个流程由一个活动或多个活动组成
 
四、Activiti使用步骤
1、部署activiti
Activiti是一个工作流引擎(其实就是一堆jar包API),业务系统访问(操作)activiti的接口,就可以方便的操作流程相关数据,这样就可以把工作流环境与业务系统的环境集成在一起。
2、流程定义
使用activiti流程建模工具(activity-designer)定义业务流程(.bpmn文件)。
 .bpmn文件就是业务流程定义文件,通过xml定义业务流程。
3、流程定义部署
activiti部署业务流程定义(.bpmn文件)。
 使用activiti提供的api把流程定义内容存储起来,在Activiti执行过程中可以查询定义的内容
 Activiti执行把流程定义内容存储在数据库中。
4、启动一个流程实例
流程实例也叫:Processlnstance
 启动一个流程实例表示开始一次业务流程的运行。
 在员工请假流程定义部署完成后,如果张三要请假就可以启动一个流程实例,如果李四要请假也启动一个流程实例,两个流程执行相互不影响。
5、用户查询待办任务(Task)
因为现在系统的业务流程已经交给activiti管理,通过activiti就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些activiti帮我们管理了,而不需要开发人员自己编写在sql语句查询。
6、用户办理任务
用户查询待办任务后,就可以办理某个任务,如果这个任务办理完成还需要其它用户办理,比如采购单创建后由部门经理审核,这个过程也是由activiti帮我们完成了。
7、流程结束
当任务办理完成没有下一个任务结点了,这个流程实例就完成了。
五、Activiti环境准备
1、下载扩展程序camunda-modeler
官网下载地址:camunda官网
 github下载地址:github下载
2、配置idea扩展程序:

然后就可以右键bpmn文件, 选择扩展
 
 
六、Activiti数据库支持
Activiti在运行时需要数据库的支持,使用25张表,把流程定义节点内容读取到数据库表中,以供后续使用。
1、Activiti支持的数据库

2、MySQL生成表
1)创建数据库activiti
2)pom依赖
2)activiti 依赖的jar 包:mybatis、alf4j、log4j等
 3) activiti 依赖的 spring 包
 4) mysgl数据库驱动
 5) 第三方数据连接池 dbcp
 6) 单元测试 Junit-4.12.jar
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <!-- bpmn-model -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <!--bpmn-converter -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <!-- activiti-json-converter -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.activiti/activiti-bpmn-layout -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>7-201802-EA</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version></version>
        </dependency>
        <dependency>
            <groupId>commons</groupId>
            <artifactId>commons-uo</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>4.12</version>
        </dependency>
         <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>org.slf4j-log4j12</artifactId>
            <version>4.12</version>
        </dependency>
 
3)log4j.properties

4)activiti.cfg.xml

5)生成Activiti表


3、表结构认识
七、Activiti使用入门案例
1、创建流程定义
2、部署流程定义
1)方式1——文件上传

 查看部署成功后数据库表数据
2)方 式2——压缩文件上传

3、启动流程实例

4、查询任务
5、流程任务处理

6、流程是心查询
7、删除流程
8、流程资源下载
9、流程历史信息查看
八、Activiti进阶
1、 流程定义与流程实例定义
流程定义 ProcessDefinition 和流程实例 ProcessInstance是Activiti中非常重要的两个概念。他们的关系其实类似于JAVA中类和对象的概念。
流程定义ProcessDefinition是以BPMN文件定义的一个工作流程,是一组工作规范。例如我们之前定义的请假流程。流程实例ProcessInstance则是指一个具体的业务流程。例如某个员工发起一次请假,就会实例化一个请假的流程实例,并且每个不同的流程实例之间是互不影响的。
在后台的表结构中,有很多张表都包含了流程定义ProcessDefinetion和流程实例Processlnstance的字段。流程定义的字段通常是PROC DEF ID,而流程实例的字段通常是PROC INST ID。
1)启动流程实例时添加Businesskey
在之前的简单案例中,我们启动一个流程实例的关键代码其实就是这一行。
ProcessInstance processInstance = runtimeService.startProcessInstanceByKev("mvLeave");
 
当我们去查看下startProcessInstanceByKey这个方法时,会看到这个方法有好几个重载的实现方法,可以传一些不同的参数。其中几个重要的参数包括
· String processDefinitionKey:流程定义的唯一键 不能为空
 ·String businessKey:每个线程实例上下文中关联的唯一键。这个也是我们这一章节要介绍的重点。
 ·Map<String,Object> variables:在线程实例中传递的流程变量。这个流程变量可以在整个流程实例中使用,后面会介绍
 到。
 ·String tenantld:租户ID,这是Activiti的多租户设计。相当于每个租户可以上来获取一个相对独立的运行环境
这一章节我们来介绍这个businessKey,业务关键字。这是Activiti提供的一个非常重要的便利,用来将activiti的工作流程与实际业务进行关联。
例如,当我们需要对一个业务订单进行审批时,订单的详细信息并不在activiti的数据当中,但是在审批时确实需要查看这些
 订单的详细信息。这个时候,就可以用这个businessKey来关联订单ID,这样在业务系统中,就可以通过这个订单ID去关联订单详细信息,审批人员就可以快速拿来进行参考。
进行实际业务整合时,这个businessKey可以根据业务场景,设计成不同的数据格式,比如关键信息逗号拼接,甚至是json都
 可以,唯一需要注意的是这个字段的数据库长度设计是255,不要超出了数据库的长度限制
接下来,我们看看如何在流程实例执行过程中获取这个业务关键字:
@Test
public void queryProcessInstance(){
// 流程定义key
String frocessDefinitionKey = "myLeave";
ProcessEngine processEngine =ProcessEnqines.qetDefaultProcessEnqine();
// 获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> list = runtimeService
.createProcessInstanceQuery()
.processDefinitionKey(processDefinitionKey)//
.list();
for (ProcessInstance processInstance :list){
System.out.println("------ ---------"); 
System.out.println("流程实例id:"
+ processInstance.qetProcessInstanceId());
System.out.println("所属流程定义id:"
+ processInstance.qetProcessDefinitionId());
System.out.println("是否执行完成:"+ processInstance.isEnded()):
System.out.println("是否暂停:"+ processInstance.isSuspended());
System.out.println("当前活动标识:"+ processInstance.getActivityId());
System.out.println("业务关键字:"+processInstance.getBusinessKey());
 
2)挂起流程&激活流程
挂起、激活流程实例
 之前我们已经测试了如何删除一个流程,有很多时候,我们只是需要暂时停止一个流程,过一段时间就要恢复。例如月底
 不接受报销审批流程,年底不接受借贷审批流程,或者非工作日不接受售后报销流程等,这个时候,就可以将流程进行挂起握
 作。挂起后的流程就不会再继续执行。
 在挂起流程时,有两种操作方式。
一种是将整个流程定义Process Definition挂起,这样,这个流程定义下的所有流程实例都将挂起,无法继续执行
2、流程变量
流程变量也是Activiti中非常重要的角色。我们之前定义的请假流程并没有用到流程变量,每个步骤都是非常固定的,但是,当我们需要实现一些复杂的业务流程,比如请假3天以内由部门经理审批,3天以上需要增加总经理审批这样的流程时,就需要用到流程变量了。
注:这个流程变量和之前介绍的业务关键字其实是有些相似的,都可以携带业务信息。并且也都可以通过activiti
 的ani查询出来,但是通常在使用过程中,应该尽量减少流程变量中的业务信息,这样能够减少业务代码对activit
 工作流的代码侵入。
 在上一章节介绍到,流程变量的类型是Map<String,Object>。所以,流程变量比业务关键字要强大很多。变量值不仅仅是字
 符串,也可以是POJO对象。但是当需要将一个POJO对象放入流程变量时,要注意这个对象必须要实现序列化接口
 serializable。
1) 流程变量的作用域
变量的作用域可以设置为Global和Local两种。
·Global变量
 这个是流程变量的默认作用域,表示是一个完整的流程实例。 Global变量中变量名不能重复。如果设置了相同的变量名,后面设置的值会直接覆盖前面设置的变量值。
 · Local变量
 Local变量的作用域只针对一个任务或一个执行实例的范围,没有流程实例大。Local变量由于作用在不同的任务或不同的执行实例中,所以不同变量的作用域是互不影响的,变量名可以相同。Local变量名也可以和Global变量名相同,不会有影响。
2)使用流程变量
定义好流程变量后,就可以在整个流程定义中使用这些流程变量了。例如可以在某些任务属性如assignee上使用 a s s i g n e e ,或者在某些连线上使用 {assignee},或者在某些连线上使用 assignee,或者在某些连线上使用{day<3}。
Activiti中可以使用UEL表达式来使用这些流程变量。UEL表达式可以直接获取一个变量的值,可以计算一个Boolean结果的表达式,还可以直接使用某些对象的属性。例如对干之前创建的请假流程,如果要实现3天以内部门经理审核,3天以上增加总经理审核,可以做如下调整:
 
3)设置全局Global流程变量
①启动流程时设置变量
②任务办理时设置变量
③通过当前流程实例设置变量
④通过当前任务设置变量
4)设置Local流程变量
3、网关
网关是用来控制流程流向的重要组件,通常都会要结合流程变量来使用。
1) 排他网关ExclusiveGateway
排他网关,用来在流程中实现决策。 当流程执行到这个网关,所有分支都会判断条件是否为true,如果为true则执行该分支,
注意:排他网关只会选择一个为true的分支执行。如果有两个分支条件都为true,排他网关会选择id值较小的一条
 分支去执行。
 为什么要用排他网关?
不用排他网关也可以实现分支,如:在连线的condition条件上设置分支条件。
在连线设置condition条件的缺点:如果条件都不满足,流程就结束了(是异常结束)。
如果 使用排他网关决定分支的走向,如下:
2) 并行网关ParallelGateway
3) 包含网关InclusiveGateway
4) 事件网关EventGatway
4、个人任务管理
在之前的简单示例中,我们已经可以通过配置Assignee属性来指定任务的负责人。但是我们之前的示例中,是简单的配置为 worker、manager、finacer等这样的固定的任务人。但是在实际工作中,往往不会是这样固定的人。可能是对应某个职位或者某个角色的系统用户。这时,这种固定分配的方式就非常不灵活了。这时,就可以使用UEL表达式配合流程变量来灵活指定。例如这样:
5、组任务分配
1)设置多个候选人
2)组任务办理流程
九、Activiti与Spring整合
十、Activiti7与SpringBoot整合
1、pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>Camunda1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Camunda1</name>
    <description>Camunda1</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.15</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <!--   springSecurity 依赖   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
 
2、application.yml
server:
  port: 7001
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/camunda?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
      username: root
      password: 123456
  activiti:
    database-schema-update: true
    db-history-used: true
    history-level: full
    check-process-definitions: false
    async-executor-activate: true
#  mvc:
#    pathmatch:
#      matching-strategy: ant_path_matcher
#  main:
#    allow-bean-definition-overriding: true
mybatis:
  mapper-locations: classpath*:mappers/*.xml
logging:
  level:
    root: info
    com.example.emos.wx.db.dao : warn
  pattern:
    console: "%d{HH:mm:ss} %-5level %msg%n"
 
3、启动类
@SpringBootApplication(exclude = {org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
public class Camunda1Application {
    
    public static void main(String[] args) {
        SpringApplication.run(Camunda1Application.class, args);
    }
}
 
4、SpringSecurityConfig
@Configuration
public class SpringSecurityConfig
        extends WebSecurityConfigurerAdapter
{}
 
5、工具类
package com.example.camunda1;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
@Slf4j
@RestController
public class TestController {
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    /**
     * 部署
     * @param file  ZIP压缩包文件
     * @param processName   流程名称
     * @return 流程部署ID
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("zipFile") MultipartFile file,
                         @RequestParam("processName") String processName) {
        String originalFilename = file.getOriginalFilename();
        if (!originalFilename.endsWith("zip")) {
            return "文件格式错误";
        }
        ProcessDefinition processDefinition = null;
        try {
            ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream());
            Deployment deployment = repositoryService.createDeployment()
                    .addZipInputStream(zipInputStream).name(processName).deploy();
            processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deployment.getId()).singleResult();
            log.info("流程部署ID:"+deployment.getId());
            log.info("流程部署Name:"+deployment.getName());
            log.error("=================================");
        } catch (IOException e) {
            log.error("流程部署失败!原因: {}", e.getMessage(), e);
        }
        return "id="+processDefinition.getDeploymentId();
    }
    /**
     * 查看流程图
     * @param deploymentId  部署ID
     * @param resourceName  图片名称
     * @param response
     * @return
     */
    @GetMapping("/getDiagram")
    public void getDiagram(@RequestParam("deploymentId") String deploymentId, @RequestParam("resourceName") String resourceName, HttpServletResponse response) {
        InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
//        response.setContentType(MediaType.IMAGE_PNG_VALUE);
        try {
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }
    /**
     * 查询流程部署列表
     */
    @GetMapping("/listDeployments")
    public List<Deployment> listDeployments() {
        List<Deployment> deployments = this.repositoryService.createDeploymentQuery().list();
        if (!deployments.isEmpty()) {
            deployments.forEach(deployment -> {
                System.out.println("流程部署Id:" + deployment.getId());
                System.out.println("流程部署Name:" + deployment.getName());
                System.out.println("流程部署DeploymentTime:" + deployment.getDeploymentTime());
                System.out.println("流程部署Key:" + deployment.getKey());
            });
        }
        return deployments;
    }
    /**
     * 查询流程定义列表
     */
    @GetMapping("/listProcessDefinitions")
    public List<ProcessDefinition> listProcessDefinitions() {
        List<ProcessDefinition> processDefinitions = this.repositoryService.createProcessDefinitionQuery()
                .list();
        if (!CollectionUtils.isEmpty(processDefinitions)) {
            processDefinitions.forEach(processDefinition -> {
                System.out.println("流程部署Id:" + processDefinition.getDeploymentId());
                System.out.println("流程定义Id:" + processDefinition.getId());
                System.out.println("流程定义Name:" + processDefinition.getName());
                System.out.println("流程定义Key:" + processDefinition.getKey());
                System.out.println("流程定义ResourceName:" + processDefinition.getResourceName());
                System.out.println("流程定义DeploymentId:" + processDefinition.getDeploymentId());
                System.out.println("流程定义Version:" + processDefinition.getVersion());
            });
        }
        return processDefinitions;
    }
    /**
     * 初始化流程实例 
     * processDefinitionKey流程定义KEY  "process_money"
     * businessKey业务表KEY(用于把业务数据与Activiti7流程数据相关联)
     */
    @GetMapping("/initProcessInstance")
    public void initProcessInstance(String processDefinitionKey, String businessKey,Map<String, Object> variables) {
        ProcessInstance processInstance = this.runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
    }
    /**
     * 通过UserId查找该用户发起的流程实例。
     */
    @GetMapping("/findTasksByUserId")
    public void findTasksByUserId(String userId) {
//        String userId ="zhangsan";
        List<Task> resultTask = taskService.createTaskQuery().taskCandidateOrAssigned(userId).list();
        System.out.println("任务列表:"+resultTask);
        // 任务列表里面。创建一个查询。通过流程id,获取指定类型的流程。
        Task task = resultTask.get(0);
        String processInstanceId = task.getProcessInstanceId();
        log.info("流程实例ID:"+task.getId());
        log.info("流程实例assignee:"+task.getAssignee());
        log.info("流程实例Name:"+task.getName());
        log.info("流程实例ExecutionId:"+task.getExecutionId());
        System.out.println("流程实例Id:"+processInstanceId);
    }
    /**
     * 根据流程实例ID查询流程实例
     * processInstanceId:流程实例ID
     */
    @GetMapping("getProcessInstance")
    public void getProcessInstance(String processInstanceId) {
//        String processInstanceId = "865523bc-bd85-11ed-b94e-005056c00008";
        ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        System.out.println("ProcessInstanceId:" + processInstance.getProcessInstanceId());
        System.out.println("ProcessDefinitionId:" + processInstance.getProcessDefinitionId());
        System.out.println("isEnded:" + processInstance.isEnded());
        System.out.println("isSuspended:" + processInstance.isSuspended());
        Map<String, Object> variables2 = processInstance.getProcessVariables();
        log.info(variables2.toString());
    }
    /**
     * 查询流程实例列表
     */
    @GetMapping("/listProcessInstances")
    public void listProcessInstances() {
        List<ProcessInstance> processInstanceList = this.runtimeService.createProcessInstanceQuery().list();
        if (!CollectionUtils.isEmpty(processInstanceList)) {
            processInstanceList.forEach(processInstance -> {
                System.out.println("ProcessInstanceId:" + processInstance.getProcessInstanceId());
                System.out.println("ProcessDefinitionId:" + processInstance.getProcessDefinitionId());
                System.out.println("isEnded:" + processInstance.isEnded());
                System.out.println("isSuspended:" + processInstance.isSuspended());
            });
        }
    }
    /**
     * 删除流程实例
     * reason:删除原因
     * processInstanceId:实例ID
     */
    public void deleteProcessInstance(String processInstanceId,String reason) {
        this.runtimeService.deleteProcessInstance(processInstanceId, reason);
    }
    /**
     * 查询所有任务列表
     */
    @GetMapping("/listTasks")
    public void listTasks() {
        List<Task> taskList = this.taskService.createTaskQuery().list();
        if (!CollectionUtils.isEmpty(taskList)) {
            taskList.forEach(task -> {
                System.out.println("Id:" + task.getId());
                System.out.println("Name:" + task.getName());
                System.out.println("Assignee:" + task.getAssignee());
                Object b = (Object) taskService.getVariable(task.getId(),"请假信息");
                log.info("a");
            });
        }
    }
    /**
     * 根据当前用户名查询代办任务
     */
    @GetMapping("/listTasksByAssignee")
    public void listTasksByAssignee(String assignee) {
        List<Task> taskList = this.taskService.createTaskQuery()
                .taskAssignee(assignee)
                .list();
        if (!CollectionUtils.isEmpty(taskList)) {
            taskList.forEach(task -> {
                System.out.println("Id:" + task.getId());
                System.out.println("Name:" + task.getName());
                System.out.println("Assignee:" + task.getAssignee());
                System.out.println("InstanceId:" + task.getProcessInstanceId());
                System.out.println("DefinitionId:" + task.getProcessDefinitionId());
            });
        }
    }
    /**
     * 完成任务
     */
    @GetMapping("/completeTask")
    public void completeTask(String taskId) {
//        String taskId = "354b9d90-477f-11ed-abfa-e4a8dfd43d4a";
        Map<String, Object> variables = new HashMap<>(16);
        this.taskService.complete(taskId, variables);
    }
}
                ![[2.2.2]进程调度的时机、方式、切换与过程](https://img-blog.csdnimg.cn/img_convert/893c90ca9af749822003a14a77822810.png)


















