Activiti5

本文详细介绍了Activiti5,一个开源的业务自动化框架。内容涵盖工作流管理系统概念,Activiti5的核心特性、数据库设计、开发环境配置、Hello World示例、流程管理、任务执行、流程变量、历史流程查询以及各种网关的使用。通过实例展示了如何部署、启动流程,以及任务的分配和处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Activiti5

Open Source Business Automation

Helping businesses solve automation challenges in distributed, highly-scalable and cost effective infrastructures.

官网链接

尚学堂B站视频,感谢up主的分享

工作流概述

工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。

工作流管理系统(Workflow Management System, WfMS)是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流规则进行工作流实例的执行。工作流管理系统不是企业的业务系统,而是为企业的业务系统的运行提供了一个软件的支撑环境。

工作流管理联盟(WfMC,Workflow Management Coalition)给出的关于工作流管理系统的定义是:工作流管理系统是一个软件系统,它通过执行经过计算的流程定义去支持一批专门设定的业务流程。工作流管理系统被用来定义、管理、和执行工作流程。

工作流管理系统的目标:管理工作的流程以确保工作在正确的时间被期望的人员所执行——在自动化进行的业务过程中插入人工的执行和干预

Activiti介绍

Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务

工作流引擎

ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。

BPMN

业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)

数据库

Activiti数据库支持:

Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。

  • ACT_RE: 'RE’表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
  • ACT_RU: 'RU’表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。*
  • ACT_ID: 'ID’表示identity。 这些表包含身份信息,比如用户,组等等。
  • ACT_HI: 'HI’表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。_
  • ACT_GE: 通用数据, 用于不同场景下,如存放资源文件。
资源库流程规则表
  • act_re_deployment 部署信息表
  • act_re_model 流程设计模型部署表
  • act_re_procdef 流程定义数据表
运行时数据库表
  • act_ru_execution 运行时流程执行实例表

  • act_ru_identitylink 运行时流程人员表,主要存储任务节点与参与者的相关信息

  • act_ru_task 运行时任务节点表

  • act_ru_variable 运行时流程变量数据表

历史数据库表
  • act_hi_actinst 历史节点表

  • act_hi_attachment 历史附件表

  • act_hi_comment 历史意见表

  • act_hi_identitylink 历史流程人员表

  • act_hi_detail 历史详情表,提供历史变量的查询

  • act_hi_procinst 历史流程实例表

  • act_hi_taskinst 历史任务实例表

  • act_hi_varinst 历史变量表

组织机构表
  • act_id_group 用户组信息表
  • act_id_info 用户扩展信息表
  • act_id_membership 用户与用户组对应信息表
  • act_id_user 用户信息表

这四张表很常见,基本的组织机构管理,关于用户认证方面建议还是自己开发一套,组件自带的功能太简单,使用中有很多需求难以满足

通用数据表
  • act_ge_bytearray 二进制数据表

  • act_ge_property 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录

Activiti5开发环境

基本的开发环境 + idea/eclipse 插件

idea -------> actiBPM

若出现中文乱码 需要在idea vm options 里增加一行

-Dfile.encoding=UTF-8

之后,就可以识别 *.bpmn文件了

pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sxt.activiti</groupId>
    <artifactId>bootDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
        <activiti.version>5.22.0</activiti.version>
    </properties>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions><!-- 去掉默认配置 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    
        <!--mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
        
        <!-- activiti的依赖 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <!-- 配置编译的jdk版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <!-- 指定source和target的版本 -->
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

其中的核心依赖

	<!-- activiti的依赖 -->
		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-engine</artifactId>
			<version>${activiti.version}</version>
		</dependency>
		<!-- web集成的时候使用 -->
		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-spring</artifactId>
			<version>${activiti.version}</version>
		</dependency>

初始化数据库

创建 activiti 数据库

 public static void main(String[] args) {

        // 创建流程引擎配置
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration
                .createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");

        // 配置实例化方式
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

        // 得到流程引擎
        ProcessEngine processEngine = configuration.buildProcessEngine();
    }

核心API

ProcessEngine

得到流程引擎常用的方法

ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();

RepositoryService

是Activiti的仓库服务类。所谓的仓库指流程定义文档的两个文件,bpmn文件流程图片

RuntimeService

是activiti的流程执行服务类。可以从这个服务类中获取很多关于流程执行相关的信息。

TaskService

是activiti的任务服务类。可以从这个类中获取任务的信息。

HistoryService

是activiti的查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息。

ProcessDefinition (act_re_procdef)

流程定义类。可以从这里获得资源文件等。当流程图被部署之后,查询出来的数据就是流程定义的数据

ProcessInstance (act_ru_execution)

代表流程定义的执行实例。如范冰冰请了一天的假,她就必须发出一个流程实例的申请。一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。流程实例就表示一个流程从开始到结束的最大的流程分支,即一个流程中流程实例只有一个。

Execution (act_ru_execution)

Activiti用这个对象去描述流程执行的每一个节点。在没有并发的情况下,Execution就是同ProcessInstance。流程按照流程定义的规则执行一次的过程,就可以表示执行对象Execution。

简单说,流程中有多条分支,那每个分支就叫一个execution,整条流程是processInstance.

TaskInstance (act_ru_task)

任务实例

Hello World

模拟请假流程

画流程图

新建一个HelloWorld.bpmn

BPMN最初是由业务流程管理倡议组织(The Business Process Management Initiative,简称BPMI)开发制定的一套业务流程建模符号,2004年5月发布了BPMN 1.0 规范。而后因为BPMI并入OMG(对象管理组织),BPMN也就随之由OMG进行维护管理。2011年,OMG推出了BPMN2.0标准,沿用至今。

如果左边的Editor不显示,需将idea进行设置,可进行如下设置

setting ----> Editor ----> Color Scheme ----> 选择Intellj Light模式

完成后,将bpmn文件改成xml文件

选择第一个设计器,打开,如果不显示Diagrams,需安装 JBoss JBPM插件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6nbznrs5-1620723592828)(C:\Users\www\AppData\Roaming\Typora\typora-user-images\image-20210420142701734.png)]

然后导出图片

部署流程
@Configuration
public class ProcessEngineConfig {

    @Bean
    public ProcessEngine getProcessEngine() {
        // 创建流程引擎配置
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration
                .createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql://121.196.30.175:3306/activiti?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");

        // 配置实例化方式
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

        // 得到流程引擎
        return configuration.buildProcessEngine();
    }
}

注入流程引擎

@Autowired
private ProcessEngine processEngine;
  @Test
    public void deployProcess() {
        //得到流程部署的service
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment().name("请假流程001")
                .addClasspathResource("HelloWorld.bpmn20.xml")
                .addClasspathResource("HelloWorld.png")
                .deploy();
        System.out.println("部署成功:流程部署ID:"+deploy.getId());
    }

注意:流程.xml文件需要加.bpmn20不然有些表的数据会不插入

源码中要求:需要以bpmn或者bpmn20.xml结尾的资源

正例:HelloWorld.bpmn20.xml

启动流程
	@Test
    public void startProcess() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String processDefinitionId="1";
        runtimeService.startProcessInstanceById(processDefinitionId);
        System.out.println("流程启动成功");
    }
查询任务
@Test
    public void findTask() {
        TaskService taskService = this.processEngine.getTaskService();
        String assignee="张三";
        List<Task> list = taskService.createTaskQuery().taskAssignee(assignee).list();
        if(null!=list&&list.size()>0) {
            for (Task task : list) {
                System.out.println("任务ID:"+task.getId());
                System.out.println("流程实例ID:"+task.getProcessInstanceId());
                System.out.println("执行实例ID:"+task.getExecutionId());
                System.out.println("流程定义ID:"+task.getProcessDefinitionId());
                System.out.println("任务名称:"+task.getName());
                System.out.println("任务办理人:"+task.getAssignee());
                System.out.println("################################");
            }
        }
    }
处理任务
    public void completeTask() {
        TaskService taskService = this.processEngine.getTaskService();
        String taskId="12504";
        taskService.complete(taskId);
        System.out.println("任务完成");
    }

管理流程定义

对流程的增加 修改 删除 查询

流程图

部署流程

流程的key相同的时候,会通过version字段来区分,默认选最新版本启动。

classpath方式部署

@Test
    public void deployProcess01() {
        // 得到流程部署的service
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment().name("请假流程001").addClasspathResource("HelloWorld.bpmn")
                .addClasspathResource("HelloWorld.png").deploy();
        System.out.println("部署成功:流程部署ID:" + deploy.getId());
    }

zip方式部署

/**
 * 部署流程使用zip 流程图的文件必须是xxxx.zip结尾
 */
@Test
public void deployProcess02() {
    // 如果不加/代表从当前包里面找文件
    // 如果加/代表从classpath的根目录里面找文件
    InputStream inputStream = this.getClass().getResourceAsStream("/HelloWorld.zip");
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    Deployment deploy = repositoryService.createDeployment().name("报销流程001").addZipInputStream(zipInputStream)// 添加流程图的流
            .deploy();// 确定部署
    System.out.println("部署成功,部署D:" + deploy.getId());
}
部署的流程查询
@Test
    public void queryProcessDeploy() {
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        // 创建部署信息的查询
        String deploymentId = "1";
        DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
        List<Deployment> list = deploymentQuery
                .deploymentId(deploymentId)
                .deploymentNameLike("请假%")
                .orderByDeploymentId()
                .desc()
                .listPage(0, 10);

        long count = deploymentQuery
                .deploymentId(deploymentId)
                .deploymentNameLike("请假%")
                .orderByDeploymentId()
                .desc()
                .count();
        for (Deployment deployment : list) {
            System.out.println("部署ID:" + deployment.getId());
            System.out.println("部署名称:" + deployment.getName());
            System.out.println("部署时间:" + deployment.getDeploymentTime());
            System.out.println("########################");
        }
        System.out.println("共查到" + count + "条");
    }
流程定义查询
  @Test
    public void queryProcDef() {
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()

		//.deploymentId("1") // 根据部署ID查询
//		.deploymentIds(deploymentIds) 根据部署ID的集合查询Set<String> deploymentIds
//		.processDefinitionId(processDefinitionId)//根据流程定义IDHelloWorld:1:4
//		.processDefinitionIds(processDefinitionIds)//根据流程定义的IDS查询
//		.processDefinitionKey("HelloWorld")//根据流程定义的的key查询
//		.processDefinitionKeyLike(processDefinitionKeyLike)//根据流程定义的的key模糊查询
//		.processDefinitionName(processDefinitionName)//根据流程定义的名称查询
//		.processDefinitionNameLike(processDefinitionNameLike)//根据流程定义的名称模糊查询
//		.processDefinitionResourceName(resourceName)//根据流程图的BPMN文件名查询
//		.processDefinitionResourceNameLike(resourceNameLike)//根据流程图的BPMN文件名模糊查询
//		.processDefinitionVersion(processDefinitionVersion)//根据流程定义的版本查询
//		.processDefinitionVersionGreaterThan(processDefinitionVersion)//version>num
//		.processDefinitionVersionGreaterThanOrEquals(processDefinitionVersion)//version>=num
//		.processDefinitionVersionLowerThan(processDefinitionVersion)//version<num
//		.processDefinitionVersionLowerThanOrEquals(processDefinitionVersion)//version<=num
                // 排序
//		.orderByDeploymentId()
//		.orderByProcessDefinitionId()
//		.orderByProcessDefinitionKey()
//		.orderByProcessDefinitionName()
//		.orderByProcessDefinitionVersion()
                // 结果集
                .list();
//		.listPage(firstResult, maxResults)\
//		.count()
//		.singleResult()
        if (null != list && list.size() > 0) {
            for (ProcessDefinition pd : list) {
                System.out.println("流程定义ID:" + pd.getId());
                System.out.println("流程部署ID:" + pd.getDeploymentId());
                System.out.println("流程定义KEY:" + pd.getKey());
                System.out.println("流程定义的名称:" + pd.getName());
                System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name
                System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name
                System.out.println("流程定义的版本号:" + pd.getVersion());
                System.out.println("##################");
            }
        }
    }
启动流程
 @Test
    public void startProcess() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String processDefinitionKey = "HelloWorld";
        runtimeService.startProcessInstanceByKey(processDefinitionKey);
        System.out.println("流程启动成功");
    }

删除流程定义
 @Test
    public void deleteProcessDef() {
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        String deploymentId = "2501";
        // 根据流程部署id删除流程定义 如果当前id的流程正在执行,那么会报错
        // repositoryService.deleteDeployment(deploymentId);
        // 根据流程部署id删除删除流程定义 如果当前id的流程正在执行,会把正在执行的流程数据删除 act_ru_*和act_hi_*表里面的数据
        repositoryService.deleteDeployment(deploymentId, true);
//		repositoryService.deleteDeploymentCascade(deploymentId);==repositoryService.deleteDeployment(deploymentId, true);
        System.out.println("删除成功");
    }
根据流程定义ID查询流程图
@Test
    public void viewProcessImg() {
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        String processDefinitionId = "HelloWorld:1:4";
        InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);

        File file = new File("d:/HelloWorld.png");
        try {
            BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = inputStream.read(b)) != -1) {
                outputStream.write(b, 0, len);
                outputStream.flush();
            }
            outputStream.close();
            inputStream.close();
            System.out.println("查询成功");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
根据流程部署查询流程图
 @Test
    public void viewProcessImg2() {
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        // 根据流程部署ID查询流程定义对象
        String deploymentId = "1";
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId).singleResult();
        // 从流程定义对象里面查询出流程定义ID
        String processDefinitionId = processDefinition.getId();
        InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);

        File file = new File("d:/" + processDefinition.getDiagramResourceName());
        try {
            BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = inputStream.read(b)) != -1) {
                outputStream.write(b, 0, len);
                outputStream.flush();
            }
            outputStream.close();
            inputStream.close();
            System.out.println("查询成功");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
查询最新的流程定义
 @Test
    public void queryNewProcessDef() {
        Map<String, ProcessDefinition> map = new HashMap<>();

        // 查询所有的流程定义根据版本号升序
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .orderByProcessDefinitionVersion().asc().list();
        if (null != list && list.size() > 0) {
            for (ProcessDefinition pd : list) {
                map.put(pd.getKey(), pd);
            }
        }
        // 循环map集合
        Collection<ProcessDefinition> values = map.values();
        for (ProcessDefinition pd : values) {
            System.out.println("流程定义ID:" + pd.getId());
            System.out.println("流程部署ID:" + pd.getDeploymentId());
            System.out.println("流程定义KEY:" + pd.getKey());
            System.out.println("流程定义的名称:" + pd.getName());
            System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name
            System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name
            System.out.println("流程定义的版本号:" + pd.getVersion());
            System.out.println("##################");
        }
    }
修改流程定义

重新部署,只要key不变,它的版本号就会+1,这样即可实现更新

任务的执行

部署流程
@Test
    public void deployProcess() {
        // 得到流程部署的service
        RepositoryService repositoryService = this.processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment().name("请假流程001").addClasspathResource("HelloWorld.bpmn")
                .addClasspathResource("HelloWorld.png").deploy();
        System.out.println("部署成功:流程部署ID:" + deploy.getId());
    }
启动流程
public void startProcess() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
//		runtimeService.startProcessInstanceById(processDefinitionId)//根据流程定义ID启动流程
        /**
         * 参数1:流程定义ID 参数2:Map<String,Object> 流程变量
         */
//		runtimeService.startProcessInstanceById(processDefinitionId, variables);
        /**
         * 参数1:流程定义ID 参数2:String 业务ID 把业务ID和流程执行实例进行绑定
         */
		//runtimeService.startProcessInstanceById(processDefinitionId, businessKey);
        /**
         * 参数1:流程定义ID 参数2:String 业务ID 把业务ID和流程执行实例进行绑定 参数3:Map<String,Object> 流程变量
         */
//		runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables)
//
//		runtimeService.startProcessInstanceByKey(processDefinitionKey)//根据流程定义的key启动
        /**
         * 参数1:流程定义的Key 参数2:Map<String,Object> 流程变量
         */
//		runtimeService.startProcessInstanceByKey(processDefinitionKey, variables)
        /**
         * 参数1:流程定义Key 参数2:String 业务ID 把业务ID和流程执行实例进行绑定
         */
//		runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey);
        /**
         * 参数1:流程定义Key 参数2:String 业务ID 把业务ID和流程执行实例进行绑定 参数3:Map<String,Object> 流程变量
         */
//		runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, variables)

        // 实际开发中使用的
        // runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, variables)
        // runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey);

        String processDefinitionKey = "HelloWorld";
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
        System.out.println("流程启动成功:" + processInstance.getId() + "   " + processInstance.getProcessDefinitionId() + "  "
                + processInstance.getProcessInstanceId());

    }

流程变量:可以决定流程图的走势

查询个人任务
 @Test
    public void queryMyTask() {
        TaskService taskService = this.processEngine.getTaskService();
        String assignee = "李四";
        List<Task> list = taskService.createTaskQuery()
                // 条件
                .taskAssignee(assignee)// 根据任务办理人查询任务
//		.deploymentId(deploymentId)//根据部署ID查询 where id=id
//		.deploymentIdIn(deploymentIds)//根据部署ID集合查询   where id in (1,2,3,4)
//		.executionId(executionId)//根据执行实例ID
//		.processDefinitionId(processDefinitionId)//根据流程定义ID
//		.processDefinitionKey(processDefinitionKey)//根据流程定义的key
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionKeyLike(processDefinitionKeyLike)
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionNameLike(processDefinitionNameLike)
//		.processInstanceBusinessKey(processInstanceBusinessKey)
                // 排序
                .orderByTaskCreateTime().desc()
                // 结果集
                .list();
//		.listPage(firstResult, maxResults)
//		.count();
//		.singleResult()

        if (null != list && list.size() > 0) {
            for (Task task : list) {
                System.out.println("任务ID:" + task.getId());
                System.out.println("任务办理人:" + task.getAssignee());
                System.out.println("执行实例ID:" + task.getExecutionId());
                System.out.println("任务名称:" + task.getName());
                System.out.println("流程定义ID:" + task.getProcessDefinitionId());
                System.out.println("流程实例ID:" + task.getProcessInstanceId());
                System.out.println("任务创建时间:" + task.getCreateTime());
                System.out.println("####################");
            }
        }
    }
处理任务
 @Test
    public void completeTask() {
        TaskService taskService = this.processEngine.getTaskService();
        String taskId = "12504";
        // 根据任务ID去完成任务
        taskService.complete(taskId);
        // 根据任务ID去完成任务并指定流程变量
//		taskService.complete(taskId, variables);
        System.out.println("任务完成");
    }
判断任务是否完成
 @Test
    public void isComplete() {
        // 已知流程实例ID
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String processInstanceId = "12504";
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        if (null != processInstance) {
            System.out.println("流程未结束");
        } else {
            System.out.println("流程已结束");
        }
根据任务判断流程是否完成
  // 已知任务ID 5002 [了解]
        // 根据任务ID查询任务实例对象
        /*
         * TaskService taskService = this.processEngine.getTaskService(); String
         * taskId="5002"; Task task =
         * taskService.createTaskQuery().taskId(taskId).singleResult();
         * //从任务实例里面取出流程实例ID String processInstanceId2 = task.getProcessInstanceId();
         * //使用流程实例ID去流程实例表里面查询有没有数据 ProcessInstanceQuery processInstance2 =
         * runtimeService.createProcessInstanceQuery().processInstanceId(
         * processInstanceId2); if (null != processInstance2) {
         * System.out.println("流程未结束"); } else { System.out.println("流程已结束"); }
         */
查询当前流程实例
// act_ru_execution
@Test
    public void queryProcessInstance() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
        if (null != list && list.size() > 0) {
            for (ProcessInstance pi : list) {
                System.out.println("执行实例ID:" + pi.getId());
                System.out.println("流程定义ID:" + pi.getProcessDefinitionId());
                System.out.println("流程实例ID:" + pi.getProcessInstanceId());
                System.out.println("########################");
            }
        }
    }

流程变量

流程变量在整个工作流中扮演很重要的作用。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是

只对应一个流程实例

也就是说各个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。

存在形式 <key,value>

部署流程
@Test
public void deployProcess() {
    // 得到流程部署的service
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    Deployment deploy = repositoryService.createDeployment().name("请假流程001").addClasspathResource("HelloWorld.bpmn")
            .addClasspathResource("HelloWorld.png").deploy();
    System.out.println("部署成功:流程部署ID:" + deploy.getId());
}
启动流程
@Test
    public void startProcess() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String processDefinitionKey = "HelloWorld";
//		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
        //创建流程变量对象
        Map<String,Object> variables=new HashMap<>();
        variables.put("请假天数", 5);//int
        variables.put("请假原因", "约会");
        variables.put("请假时间", new Date());
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
        System.out.println("流程启动成功:" + processInstance.getId() + "   " + processInstance.getProcessDefinitionId() + "  "
                + processInstance.getProcessInstanceId());

    }
设置流程参数
@Test
    public void setVariables() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String executionId="2501";
        //runtimeService.setVariable(executionId, "请假人", "小明");
        Map<String,Object> variables=new HashMap<>();
        variables.put("请假天数", 6);//int
        variables.put("请假原因", "约会妹子");
        variables.put("请假时间", new Date());
        variables.put("用户对象", new User(1,"小明"));
        runtimeService.setVariables(executionId, variables);
        System.out.println("流程变量设置成功");
}
设置流程参数2
@Test
    public void setVariables2() {
        TaskService taskService = this.processEngine.getTaskService();

        String taskId="2507";
        //runtimeService.setVariable(executionId, "请假人", "小明");
        Map<String,Object> variables=new HashMap<>();
        variables.put("任务ID设置的", 9);//int
//		taskService.setVariable(taskId, variableName, value);
        taskService.setVariables(taskId, variables);
        System.out.println("流程变量设置成功");
    }
获取流程变量
@Test
    public void getVariables() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String executionId="2501";
        Integer days=(Integer) runtimeService.getVariable(executionId, "请假天数");
        Date date=(Date) runtimeService.getVariable(executionId, "请假时间");
        User user=(User) runtimeService.getVariable(executionId, "用户对象");
        System.out.println(days);
        System.out.println(date.toLocaleString());
        System.out.println(user.getId()+"  "+user.getName());
    }
查询历史流程变量
 public void getHistoryVariables() {
        HistoryService historyService = this.processEngine.getHistoryService();

		/*HistoricVariableInstance singleResult = historyService.createHistoricVariableInstanceQuery().id("2503").singleResult();;
		System.out.println(singleResult.getId());
		System.out.println(singleResult.getValue());
		System.out.println(singleResult.getVariableName());
		System.out.println(singleResult.getVariableTypeName());*/
        String processInstanceId="2501";
        List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();

        for (HistoricVariableInstance hvs : list) {
            System.out.println("ID"+hvs.getId());
            System.out.println("变量值"+hvs.getValue());
            System.out.println("变量名"+hvs.getVariableName());
            System.out.println("变量类型"+hvs.getVariableTypeName());
            System.out.println("#####################");
        }
    }
设置Local流程变量
@Test
public void setVariables3() {
        RuntimeService runtimeService = this.processEngine.getRuntimeService();
        String executionId="2501";
        //runtimeService.setVariable(executionId, "请假人", "小明");
        Map<String,Object> variables=new HashMap<>();
        variables.put("测试", "约会妹子");
        runtimeService.setVariablesLocal(executionId, variables);
        System.out.println("流程变量设置成功");
    }
    
     @Test
    public void setVariables4() {
        TaskService taskService = this.processEngine.getTaskService();
        String taskId="2507";
        //runtimeService.setVariable(executionId, "请假人", "小明");
        Map<String,Object> variables=new HashMap<>();
        variables.put("测试2", 9);//int
        taskService.setVariablesLocal(taskId, variables);
        System.out.println("流程变量设置成功");
    }

Local流程变量和普通变量区别

  • 普通变量
    • 不会去设置task_id
    • 可以理解成一个执行示例内共享的
  • Local变量
    • 绑定了当前任务,所以下一个任务是取不到该变量的

历史流程

查询历史流程示例
@Test
    public void historyProcessInstince() {
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
                //条件
//		.processDefinitionId(processDefinitionId)
//		.processDefinitionKey(processDefinitionKey)
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionVersion(processDefinitionVersion)
//		.processInstanceBusinessKey(processInstanceBusinessKey)
//		.processInstanceId(processInstanceId)
//		.processInstanceIds(processInstanceIds)
                //排序
//		.orderByProcessDefinitionId()
//		.orderByProcessInstanceBusinessKey()
//		.orderByProcessInstanceDuration()
//		.orderByProcessInstanceStartTime()
//		.orderByProcessInstanceId()
                //结果集
                .list();
//		.listPage(firstResult, maxResults)
//		.count()
//		.singleResult();

        if(null!=list&&list.size()>0) {
            for (HistoricProcessInstance hpi : list) {
                System.out.println("历史流程实例ID:" + hpi.getId());
                System.out.println("流程定义ID:" + hpi.getProcessDefinitionId());
                System.out.println("历史流程实例的业务ID:" + hpi.getBusinessKey());
                System.out.println("流程部署ID:" + hpi.getDeploymentId());
                System.out.println("流程定义KEY:" + hpi.getProcessDefinitionKey());
                System.out.println("开始活动ID:" + hpi.getStartActivityId());
                System.out.println("结束活动ID:" + hpi.getEndActivityId());
                System.out.println("########################");
            }
        }

    }
查询历史活动节点
   @Test
    public void queryHistoryAct() {
        List<HistoricActivityInstance> list = this.historyService.createHistoricActivityInstanceQuery()
                //条件
//		.activityId(activityId)
//		.activityInstanceId(activityInstanceId)
//		.activityName(activityName)
                //排序
//		.orderByActivityId()
//		.orderByActivityName()
                //结果集
                .list();
        if(null!=list&&list.size()>0)
        {
            for (HistoricActivityInstance hai : list) {
                System.out.println("ID:"+hai.getId());
                System.out.println("流程定义ID:"+hai.getProcessDefinitionId());
                System.out.println("流程实例ID:"+hai.getProcessInstanceId());
                System.out.println("执行实例ID:"+hai.getExecutionId());
                System.out.println("活动ID:"+hai.getActivityId());
                System.out.println("任务ID:"+hai.getTaskId());
                System.out.println("活动名称:"+hai.getActivityName());
                System.out.println("活动类型:"+hai.getActivityType());
                System.out.println("任务办理人:"+hai.getAssignee());
                System.out.println("开始时间:"+hai.getStartTime());
                System.out.println("结束时间:"+hai.getEndTime());
                System.out.println("持续时间:"+hai.getDurationInMillis());
                System.out.println("#######################################");
            }
        }
    }
查询历史任务
    @Test
    public void queryHistoryTask() {
        List<HistoricTaskInstance> list = this.historyService.createHistoricTaskInstanceQuery()
                //条件
//		.deploymentId(deploymentId)
//		.deploymentIdIn(deploymentIds)
//		.executionId(executionId)
//		.processDefinitionId(processDefinitionId)
//		.processDefinitionKey(processDefinitionKey)
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionKeyLike(processDefinitionKeyLike)     processDefinitionKeyLike="%Hello%"
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionNameLike(processDefinitionNameLike)
                //排序
//		.orderByTaskDefinitionKey()
                //结果集
                .list();
//		.listPage(firstResult, maxResults)
//		.count()
//		.singleResult()
        if(null!=list&&list.size()>0)
        {
            for (HistoricTaskInstance task : list) {
                System.out.println("任务ID:" + task.getId());
                System.out.println("任务办理人:" + task.getAssignee());
                System.out.println("执行实例ID:" + task.getExecutionId());
                System.out.println("任务名称:" + task.getName());
                System.out.println("流程定义ID:" + task.getProcessDefinitionId());
                System.out.println("流程实例ID:" + task.getProcessInstanceId());
                System.out.println("任务创建时间:" + task.getCreateTime());
                System.out.println("任务结束时间:" + task.getEndTime());
                System.out.println("#######################################");
            }
        }
    }

连线

核心:通过流程变量,判断流程走向

gQn7Ss.png

处理流程
@Test
    public void completeTask() {
        TaskService taskService = this.processEngine.getTaskService();
        String taskId = "7503";
        //Map<String, Object> variables = new HashMap<>();
        //variables.put("outcome", "重要");
        // 根据任务ID去完成任务
         taskService.complete(taskId);
        // 根据任务ID去完成任务并指定流程变量
		//taskService.complete(taskId, variables);
        System.out.println("任务完成");
    }

排他网关

排他网关类似于 if、if-else、if-else、else

glK70x.png

处理流程
  @Test
    public void completeTask2() {
        TaskService taskService = this.processEngine.getTaskService();
        String taskId = "20004";
        Map<String, Object> variables=new HashMap<>();
        variables.put("money", 1200);
        // 根据任务ID去完成任务并指定流程变量
        taskService.complete(taskId, variables);
        System.out.println("任务完成");
    }

并行网关

同时执行

下图启动后,会生成付款、发货两个任务

excution中会有三条记录,三个执行实例的流程实例是同一个

个人任务

之前创建流程图时候,办理人是事先写好的,后续不能修改,所以需动态分配

分配方式一(事先定义)
分配方式二(流程变量)

执行下一个节点前,先设置流程变量,指定办理人

分配方式二(使用类)
public class TaskListenerImpl implements TaskListener {

    @Override
    public void notify(DelegateTask delegateTask) {
        System.out.println("我来了");
        String assignee = "李四";
        delegateTask.setAssignee(assignee);
    }
}

组任务(动态指定一组成员里里某个人来处理下一个任务)

一个流程节点的办理人是一个,但是希望能给多个人看到该任务,类似于抄送的功能

分配方式一(直接指定组成员)

流程启动后,act_ru_task表中不会有办理人需要手动拾取,act_ru_identitylink表中每个组成员都会有两条数据

  • candidate 候选者
  • participant 参与者
查询组任务
@Test
public void findGroupTask() {
   TaskService taskService = this.processEngine.getTaskService();
   String candidateUser = "小B";
   List<Task> list = taskService.createTaskQuery().taskCandidateUser(candidateUser).list();
   if (null != list && list.size() > 0) {
      for (Task task : list) {
         System.out.println("任务ID:" + task.getId());
         System.out.println("流程实例ID:" + task.getProcessInstanceId());
         System.out.println("执行实例ID:" + task.getExecutionId());
         System.out.println("流程定义ID:" + task.getProcessDefinitionId());
         System.out.println("任务名称:" + task.getName());
         System.out.println("任务办理人:" + task.getAssignee());
         System.out.println("################################");
      }
   }
}
任务拾取(组任务变成个人任务)
@Test
	public void claim() {
		String taskId="2505";
		TaskService taskService = this.processEngine.getTaskService();
		taskService.claim(taskId, "小A");
		System.out.println("任务拾取成功");
	}

拾取后,去查候选人任务就查不到了

任务回退
@Test
	public void claimBack() {
		String taskId="2504";
		TaskService taskService = this.processEngine.getTaskService();
		taskService.setAssignee(taskId, null);
		System.out.println("任务回退成功");
	}
查询任务成员列表
 @Test
    public void findGroupUser(){
        String taskId = "2504";
        List<IdentityLink> list = processEngine.getTaskService()//
                        .getIdentityLinksForTask(taskId);
         //List<IdentityLink> list = processEngine.getRuntimeService()//
        //                .getIdentityLinksForProcessInstance(instanceId);
        for(IdentityLink identityLink:list ){
            System.out.println("userId="+identityLink.getUserId());
            System.out.println("taskId="+identityLink.getTaskId());
            System.out.println("piId="+identityLink.getProcessInstanceId());
            System.out.println("TYPE="+identityLink.getType());
            System.out.println("######################");
        }
    }
添加组成员
@Test
	public void addGroupUser() {
		String taskId="2504";
		TaskService taskService = this.processEngine.getTaskService();
		taskService.addCandidateUser(taskId, "小E");
		System.out.println("添加组成员成功");
	}

删除组成员

@Test
	public void deleteGroupUser() {
		String taskId="2504";
		TaskService taskService = this.processEngine.getTaskService();
		taskService.deleteCandidateUser(taskId, "小E");
		System.out.println("添加组成员成功");
	}
分配方式二(使用流程变量)

分配方式三(使用类)
public class GroupTaskListenerImpl implements TaskListener{

	@Override
	public void notify(DelegateTask delegateTask) {
		System.out.println("进来了");
		delegateTask.addCandidateUser("小A");
		delegateTask.addCandidateUser("小B");
		delegateTask.addCandidateUser("小C");
		delegateTask.addCandidateUser("小D");
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值