springboot整合Activiti-常用方法(部署、启动、查询、执行任务)
作者:mmseoamin日期:2024-01-22

Activiti-常用方法

  • 一、springboot整合activiti7
    • 1、activiti7的核心依赖
    • 2、yml配置
    • 3、activiti7默认生成的表
    • 二、部署流程
      • 1、静态部署流程
      • 2、动态部署流程
      • 3、部署流程相关联表
      • 三、启动流程
        • 1、startProcessInstanceByKey(推荐使用)
        • 2、startProcessInstanceByKeyAndTenantId(推荐使用)
        • 3、startProcessInstanceById
        • 4、startProcessInstanceByMessage
        • 5、startProcessInstanceByMessageAndTenantId
        • 四、任务执行
          • 1、任务查询
          • 2、拾取任务
          • 3、归还任务
          • 4、查询任务候选人
          • 5、查询当前用户待审核的任务
          • 6、执行待审核的任务
          • 7、其他

            一、springboot整合activiti7

            ps:activiti7强依赖security,所以还需要整合security,这里就当整合成功了。

            真不会整合,就看我下面这个博文

            日常记录-SpringBoot整合SpringSecurity(前后分离)+JWT+Redis

            1、activiti7的核心依赖

            
            
                org.activiti
                activiti-spring-boot-starter
                7.1.0.M6
                
                    
                        mybatis
                        org.mybatis
                    
                
            
            
            
                org.springframework.boot
                spring-boot-starter-security
            
            

            2、yml配置

            spring:
              activiti:
                #自动更新数据库结构
                #1.flase:默认值。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
                #2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
                #3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
                #4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
                database-schema-update: false
                #activiti7默认不生成历史信息表,开启历史表
                db-history-used: false
                #记录历史等级 可配置的历史级别有none, activity, audit, full
                #none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
                #activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
                #audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
                #full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
                history-level: none
                # =============================
                #自动检查、部署流程定义文件
                check-process-definitions: false
                # 关闭 SpringAutoDeployment never-fail
                deployment-mode: never-fail
                # asyncExecutorActivate是指activiti在流程引擎启动就激活AsyncExecutor,异步:true-开启(默认)、false-关闭
                async-executor-activate: true
                #流程定义文件存放目录,要具体到某个目录
                #      process-definition-location-prefix: classpath:/processes/holliday/
                #process-definition-location-suffixes: #流程文件格式
                #  - **.bpmn20.xml
                #  - **.bpmn
            

            3、activiti7默认生成的表

            启动成功后就看到下面的表

            1. activiti7默认不生成act_hi历史表
            2. 如果不生成历史表,还需要禁用插入历史数据【spring.activiti.history-level:=none】

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第1张

            activiti常用的服务

               @Autowired
                private RepositoryService repositoryService;
                @Autowired
                private RuntimeService runtimeService;
                @Autowired
                private TaskService taskService;
            

            二、部署流程

            1、静态部署流程

            java代码

            //使用RepositoryService进行部署
            DeploymentBuilder builder = repositoryService.createDeployment();
            builder.addClasspathResource("bpmn/demo1/demo1.bpmn20.xml");
            builder.addClasspathResource("bpmn/demo1/demo1.png");
            builder.tenantId("212121");//区分同一个流程所属系统,该值主要用于记录启动的流程实例归属于哪个系统。
            builder.name("串行并行配置工作流");
            Deployment deployment = builder.deploy();
            //输出部署信息
            System.out.println("流程部署id:" + deployment.getId());
            System.out.println("流程部署名称:" + deployment.getName());
            

            bpmn文件路径

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第2张

            2、动态部署流程

            controller代码

            /**
                 * 部署流程
                 * @param fileBpmn bpmn文件
                 * @param fileSvg  svg图片
                 * @param name     流程名称
                 * @param key      流程key
                 * @param tenantId 系统标识 -> 同一个流程可以部署多次,互不干扰,系统标识必须唯一
                 * @return
                 */
                @PostMapping(value="/saveDeploy")
                public ApiResult saveDeploy(@RequestPart(name = "fileBpmn", required = true) MultipartFile fileBpmn,
                                            @RequestPart(name = "fileSvg", required = true) MultipartFile fileSvg,
                                            @RequestParam("name") String name,
                                            @RequestParam("key") String key,
                                            @RequestParam("tenantId") String tenantId){
                    
                    activitiService.saveDeploy(fileBpmn,fileSvg,name,key,tenantId);
                    return ApiResult.ok("成功");
                }
            

            service代码

            void saveDeploy(MultipartFile fileBpmn, MultipartFile fileSvg, String name, String key,String tenantId);
            

            serviceImpl代码

             @Override
                public void saveDeploy(MultipartFile fb, MultipartFile fg, String name, String key,String tenantId) {
                    //1:使用File 类创建一个要操作的文件路径
                    //File file = new File("D:" + File.separator + bpmnZip);
                   /* File fileBpmn = new File("D:" + File.separator + fb);
                    File fileSvg = new File("D:" + File.separator + fg);*/
                    //System.out.println(file.getPath());
                    InputStream inputStreamBpmn = null;
                    InputStream inputStreamSvg = null;
                    try {
                        inputStreamBpmn = fb.getInputStream();
                        inputStreamSvg = fg.getInputStream();
                        /*
                        这是压缩包部署
                        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
                        System.out.println(inputStream);
                        */
                        // 流程部署
                        Deployment deployment = repositoryService.createDeployment()
                                .name(name)
                                .key(key)
                                .addInputStream(fb.getOriginalFilename(),inputStreamBpmn)
                                .addInputStream(fg.getOriginalFilename(),inputStreamSvg)
                                //.category("vvvv")
                                .tenantId(tenantId)
                                //.addZipInputStream(zipInputStream)
                                .deploy();
                        System.out.println("流程部署id:" + deployment.getId());
                        System.out.println("流程部署名称:" + deployment.getName());
                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        try {
                            inputStreamBpmn.close();
                            inputStreamSvg.close();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            

            3、部署流程相关联表

            部署成功后,这几张表会有数据

            act_ge_bytearray(二进制数据表,存储通用的流程定义和流程资源)

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第3张

            act_re_deployment(部署单元信息表)

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第4张

            act_re_procdef(已部署的流程定义)

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第5张

            三、启动流程

            1、startProcessInstanceByKey(推荐使用)

            //参数 processDefinitionKey -> act_re_procdef.KEY_
            //参数 businessKey -> 一般是你业务的唯一标识,把该流程和你的业务绑定一起
            //参数 Map variables -> 流程变量
            ProcessInstance startProcessInstanceByKey(String processDefinitionKey);
            ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey);
            ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map variables);
            ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey, Map variables);
            

            2、startProcessInstanceByKeyAndTenantId(推荐使用)

            //参数 processDefinitionKey -> act_re_procdef.KEY_
            //参数 businessKey -> 一般是你业务的唯一标识,把该流程和你的业务绑定一起
            //参数 Map variables -> 流程变量
            //参数 tenantId -> 系统唯一标识(类似同一型号的手机有不同的串码)
            ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String tenantId);
            ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String businessKey, String tenantId);
            ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, Map variables, String tenantId);
            ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String businessKey, Map variables, String tenantId);
            

            3、startProcessInstanceById

            //参数 processDefinitionId-> act_re_procdef.ID_
            //参数 businessKey -> 一般是你业务的唯一标识,把该流程和你的业务绑定一起
            //参数 Map variables -> 流程变量
            ProcessInstance startProcessInstanceById(String processDefinitionId);
            ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey);
            ProcessInstance startProcessInstanceById(String processDefinitionId, Map variables);
            ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey, Map variables);
            

            获取processDefinitionId的java代码

                    //一般来说,你也不会设置key和tenantId一样的数据
                    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
                    ProcessDefinition processDefinition = processDefinitionQuery.processDefinitionKey("demo1").processDefinitionTenantId("212121").singleResult();
                    System.out.println("processDefinition的主键ID:"+processDefinition.getId());
                    //通过processDefinitionId启动流程
                    ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
                    //输出实例信息
                    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
                    System.out.println("流程实例id:" + processInstance.getId());
                    System.out.println("当前活动Id:" + processInstance.getActivityId());
            

            4、startProcessInstanceByMessage

            部署流程的时候没有配tenantId

            ProcessInstance startProcessInstanceByMessage(String messageName);
            ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey);
            ProcessInstance startProcessInstanceByMessage(String messageName, Map processVariables);
            ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map processVariables);
            

            5、startProcessInstanceByMessageAndTenantId

            部署流程的时候有配tenantId

            ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, String tenantId);
            ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, String businessKey, String tenantId);
            ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, Map processVariables, String tenantId);
            ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, String businessKey, Map processVariables, String tenantId);
            

            实例

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第6张

            message 和 process 是同级的
            
            

            如果start事件用了messageRef,一定要配相应的message

            act_ru_event_subscr表(运行时事件),部署成功就有数据了

            springboot整合Activiti-常用方法(部署、启动、查询、执行任务),在这里插入图片描述,第7张

            java代码1

            ProcessInstance processInstance = runtimeService.startProcessInstanceByMessageAndTenantId("testMessage","888888");
            //输出实例信息
            System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
            System.out.println("流程实例id:" + processInstance.getId());
            System.out.println("当前活动Id:" + processInstance.getActivityId());
            

            java代码2

            //
            Execution execution = runtimeService.createExecutionQuery().messageEventSubscriptionName("testMessage").singleResult();
            log.info("execution = {}", execution);
            runtimeService.messageEventReceived("testMessage",execution.getId());
            

            四、任务执行

            1、任务查询

             //TaskService已经封装好了,根据自己的业务查询,这里只是简单的演示
             //根据流程key查询任务
             List list = taskService.createTaskQuery()
                     .processDefinitionKey("demo1")//act_re_procdef.KEY_
                     //.taskAssignee() //任务负责人 
                     .list();
             for (Task task : list) {
                 System.out.println("流程实例id:" + task.getProcessInstanceId());
                 System.out.println("任务id:" + task.getId());
                 System.out.println("任务负责人:" + task.getAssignee());
                 System.out.println("任务名称:" + task.getName());
             }
            

            2、拾取任务

            // 可以拾取任务
            //参数1 任务id
            //参数2 负责人名称
            taskService.claim("41691bf7-47c9-11ee-af01-002b67defec7","负责人名称");
            

            3、归还任务

            // 如果设置为null,归任务没有负责人
            taskService.setAssignee("41691bf7-47c9-11ee-af01-002b67defec7",null);
            

            4、查询任务候选人

            //查询任务候选人
            //参数1 任务id
            List identityLinkList = taskService.getIdentityLinksForTask("41691bf7-47c9-11ee-af01-002b67defec7");
            for (IdentityLink identityLink : identityLinkList) {
                System.out.println(identityLink.getUserId());
            }
            

            5、查询当前用户待审核的任务

            // 查看当前用户待审核记录(任务给别人拾取也能查询)
            //参数1 你定义的用户名称或用户id
            List list = taskService.createTaskQuery().taskInvolvedUser("user1")
                    .orderByTaskCreateTime().desc()
                    .list();// 代办列表
            for (Task task : list) {
                System.out.println("流程实例id:" + task.getProcessInstanceId());
                System.out.println("任务id:" + task.getId());
                System.out.println("任务负责人:" + task.getAssignee());
                System.out.println("任务名称:" + task.getName());
            }
            

            6、执行待审核的任务

            //先查询任务是否给当前用户拾取了
            Task task = taskService.createTaskQuery()
                    .taskId("任务id")
                    .taskAssignee("负责人名称")
                    .singleResult();
            //再执行任务
            if(task != null){
                taskService.complete("任务id");
                System.out.println("完成任务");
            }
            

            7、其他

            常用的服务就这三个了,基本能满足大部分需求

            @Autowired
            private RepositoryService repositoryService;
            @Autowired
            private RuntimeService runtimeService;
            @Autowired
            private TaskService taskService;