• acvitivi笔记(2)


    一、个人任务

    1. 分配任务负责人

    在进行业务流程建模时指定固定的任务负责人,
    在 properties 视图中,填写 Assignee 项为任务负责人。
    由于固定分配方式,任务只管一步一步执行任务,执行到每一个任务将按照 bpmn 的配置去分配任 务负责人

    在这里插入图片描述

    2. 表达式分配

    Activiti使用 UEL 表达式,UEL 是 java EE6规范的一部分,UEL(Unified Expression Language)即统一表达式语言,activiti支持两个 UEL表达式:UEL-value 和 UEL-method。

    1)UEL-value 定义如下:

    assignee 这个变量是 activiti的一个流程变量。

    在这里插入图片描述

    user 也是 activiti的一个流程变量,user.assignee 表示通过调用 user 的 getter方法获取值。
    在这里插入图片描述

    2)UEL-method方式如下:

    userBean 是 spring容器中的一个 bean,表示调用该 bean 的 getUserId()方法。

    UEL-method 与UEL-value 结合
    再比如: ${ldapService.findManagerForEmployee(emp)} ldapService 是 spring容器的一个bean,findManagerForEmployee是该 bean 的一个方法,emp 是 activiti 流程变量,emp作为参数传到 ldapService.findManagerForEmployee 方法中。

    其它
    表达式支持解析基础类型、bean、list、array 和 map,也可作为条件判断。 如下: ${order.price > 100 && order.price < 250}

    在这里插入图片描述

    3)使用流程变量分配任务

    在这里插入图片描述

    启动流程实例时设计流程变量 //定义流程变量
    Map<String, Object> variables = new HashMap<String, Object>(); //设置流程变量assignee variables.put(“assignee”, “张三”); ProcessInstance processInstance = runtimeService .startProcessInstanceByKey(processDefinitionKey, variables);

    注意事项
    由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如: 某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在 流程变量中存在,否则 activiti异常。

    3. 监听器分配

    任务监听器是发生对应的任务相关事件时执行自定义 java 逻辑 或表达式。 任务相当事件包括:

    • create:任务创建后触
    • Assignment:任务分配后触发
    • Delete:任务完成后触发
    • All:所有事件发生都触发

    在这里插入图片描述

    java 逻辑 或表达式: 表达式参考上边的介绍的UEL 表达式,这里主要介绍监听类使用。
    定义任务监听类,且类必须实现 org.activiti.engine.delegate.TaskListener接口
    注意事项
    使用监听器分配方式,按照监听事件去执行监听类的 notify 方法,方法如果不能正常执行也会影响 任务的执行

    public class MyTaskListener implements TaskListener {
        @Override
        public void notify(DelegateTask delegateTask) {
            这里指定任务负责人 delegateTask.setAssignee("张三");
        }
    }
    

    二、流程变量

    流程变量作用域

    流程变量的作用域默认是一个流程实例(processInstance),也可以是一个任务(task)或一个执行实例 (execution),这三个作用域流程实例的范围最大,可以称为 global变量,任务和执行实例仅仅是针对 一个任务和一个执行实例范围,范围没有流程实例大,称为 local变量。

    • global变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值。
    • Local变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。
    • Local变量名也可以和 global变量名相同,没有影响。

    注意:如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无 法反序列化,需要生成 serialVersionUID。

    使用方法

    第一步:设置流程变量 第二步:通过 UEL表达式使用流程变量 1> 可以在 assignee 处设置 UEL表达式,表达式的值为任务的负责人 比如:${assignee},assignee 就是一个流程变量名称

    1. Activiti获取 UEL 表达式的值 ,即流程变量 assignee 的值 ,将 assignee 的值作为任务的负责人 进行任务分配
    1. 可以在连线上设置 UEL表达式,决定流程走向 比如: p r i c e > = 10000 和 {price>=10000}和 price>=10000{price<10000}: price 就是一个流程变量名称,uel 表达式结果类型为 布尔类型
      如果 UEL表达式是 true,要决定 流程执行走向

    使用Global变量控制流程

    需求
    员工创建请假申请单,由部门经理审核,部门经理审核通过后请假 3 天及以下由人事经理直接 审核,3 天以上先由总经理审核,总经理审核通过再由人事经理存档。
    在这里插入图片描述
    在这里插入图片描述

    1. 启动流程时设置

    startProcessInstanceByKey(processDefinitionKey, variables)流程变量作用域是一个流 程实例,流程变量使用 Map存储,同一个流程实例设置变量map 中 key 相同,后者覆盖前者。
    示例代码:

          //新的请假流程定义的部署
        @Test
        public void deploy() {
            //1.得到ProcessEngine
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
    
            //3.部署
            Deployment deploy = repositoryService.createDeployment()
                    .addClasspathResource("diagram/holiday4.bpmn")
                    .addClasspathResource("diagram/holiday4.png")
                    .name("请假流程-流程变量")
                    .deploy();
    
            System.out.println(deploy.getId());
            System.out.println(deploy.getName());
        }
    
    
        //启动流程实例,同时还要设置流程变量的值
        // act_ge_bytearray
        // act_ru_variable
        @Test
        public void startProcess() {
            //1.得到ProcessEngine
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RuntimeService
            RuntimeService runtimeService = processEngine.getRuntimeService();
    
            //3.流程定义的key问题   myProcess_1
            String key = "myProcess_1";
            Map<String, Object> map = new HashMap<>();
    
            Holiday holiday = new Holiday();
            holiday.setNum(5F);
            map.put("holiday", holiday);
    
            //4.启动流程实例,并且设置流程变量的值
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, map);
    
            //5.输出实例信息
            System.out.println(processInstance.getName());
            System.out.println(processInstance.getProcessDefinitionId());
    
        }
    
        //完成任务  zhangsan  -----lishi----判断流程变量的请假天数,1天----分支:人事经理存档(zhaoliu)
        @Test
        public  void completeTsak() {
            //1.得到ProcessEngine
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService
            TaskService taskService = processEngine.getTaskService();
    
            //3.查询当前用户是否有任务
            String key = "myProcess_1";
            Task task = taskService.createTaskQuery().processDefinitionKey(key)
                    .taskAssignee("zhaoliu").singleResult();
    
            //4.判断task!=null,说明当前用户有任务
            if (task != null) {
                taskService.complete(task.getId());
                System.out.println("任务执行完毕");
            }
        }
    

    结果
    在这里插入图片描述
    定义的数据
    在这里插入图片描述

    2. 任务办理时设置

    在完成任务时设置流程变量,该流程变量只有在该任务完成后其它结点才可使用该变量,它的作用 域是整个流程实例,如果设置的流程变量的 key 在流程实例中已存在相同的名字则后设置的变量替 换前边设置的变量。

    说明: 通过当前任务设置流程变量,需要指定当前任务 id,如果当前执行的任务 id 不存在则抛出异常。 任务办理时也是通过map<key,value>设置流程变量,一次可以设置多个变量。

        @Test
        public void completeTsak() {
            //1.得到ProcessEngine
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService
            TaskService taskService = processEngine.getTaskService();
    
            //3.查询当前用户是否有任务
            String key = "myProcess_1";
            Task task = taskService.createTaskQuery().processDefinitionKey(key)
                    .taskAssignee("zhaoliu").singleResult();
    
            //初始化一些参数
            Map<String, Object> map = new HashMap<>();
    
            Holiday holiday = new Holiday();
            holiday.setNum(5F);
            map.put("holiday", holiday);
            //4.判断task!=null,说明当前用户有任务
            if (task != null) {
                taskService.complete(task.getId(),map);
                System.out.println("任务执行完毕");
            }
        }
    

    在这里插入图片描述

    3. 通过当前流程实例设置

    通过流程实例 id 设置全局变量,该流程实例必须未执行完成。

    注意: executionId 必须当前未结束 流程实例的执行 id,通常此 id 设置流程实例 的 id。 也可以通过 runtimeService.getVariable()获取流程变量

           public static void main(String[] args) {
            //1.得到ProcessEngine
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RuntimeService
            RuntimeService runtimeService = processEngine.getRuntimeService();
    
            //3.流程定义的key问题   myProcess_1
            //Map<String ,Object> map = new HashMap<>();
    
            Holiday holiday = new Holiday();
            holiday.setNum(5F);
            // map.put("holiday",holiday);
    
            //4.通过实例id,来设置流程变量
            //第一个参数:流程实例的id
            //第二个参数:流程变量名
            //第三个变量:流程变量名,所对应的值
            runtimeService.setVariable("2501", "holiday", holiday);
            //一次设置多个值    
            //runtimeService.setVariables(executionId, variables) 
        }
    

    4. 通过当前任务设置

    注意: 任务id必须是当前待办任务id,act_ru_task中存在。如果该任务已结束,报错:
    也可以通过 taskService.getVariable()获取流程变量

    在这里插入图片描述

    public void setGlobalVariableByTaskId() {
            //当前待办任务id
            String taskId = "1404";
            TaskService taskService = processEngine.getTaskService();
            Holiday holiday = new Holiday();
            holiday.setNum(3);
            //通过任务设置流程变量 taskService.
            setVariable(taskId, "holiday", holiday);
            //一次设置多个值    
            taskService.setVariables(taskId, variables);
        }
    

    5.注意事项

    1. 如果 UEL表达式中流程变量名不存在则报错。
    2. 如果 UEL表达式中流程变量值为空NULL,流程不按 UEL 表达式去执行,而流程结束 。
    3. 如果 UEL表达式都不符合条件,流程结束
    4. 如果连线不设置条件,会走 flow 序号小的那条线
    5. 设置流程变量会在当前执行流程变量表插入记录,同时也会在历史流程变量表也插入记录。

    SELECT * FROM act_ru_variable #当前流程变量表 记录当前运行流程实例可使用的流程变量,包括 global和 local变量
    Id_:主键
    Type_:变量类型
    Name_:变量名称
    Execution_id_:所属流程实例执行 id,
    global和 local变量都存储 Proc_inst_id_:所属流程实例 id,global和 local变量都存储 Task_id_:所属任务 id,local变量存储 Bytearray_:serializable 类型变量存储对应act_ge_bytearray 表的 id Double_:double 类型变量值 Long_:long类型变量值 Text_:text 类型变量值

    SELECT * FROM act_hi_varinst #历史流程变量表 记录所有已创建的流程变量,包括 global和 local变量 字段意义参考当前流程变量表

    字段名称字段描述数据类型主键为空取值说明
    ID_ID_nvarchar(64)主键标识
    REV_乐观锁int乐观锁
    TYPE_类型nvarchar(255)备注9
    NAME_名称nvarchar(255)变量名称
    EXECUTION_ID_执行实例IDnvarchar(64)执行的ID
    PROC_INST_ID_流程实例IDnvarchar(64)流程实例ID
    TASK_ID_节点实例IDnvarchar(64)节点实例ID(Local)
    BYTEARRAY_ID_字节表IDnvarchar(64)字节表的ID(ACT_GE_BYTEARRAY)
    DOUBLE_DOUBLE_float存储变量类型为Double
    LONG_LONG_numeric(19)存储变量类型为long
    TEXT_TEXT_nvarchar(4000)‘存储变量值类型为String 如此处存储持久化对象时,值jpa对象的class
    TEXT2_TEXT2_nvarchar(4000)此处存储的是JPA持久化对象时,才会有值。此值为对象ID

    三、组任务

    需求

    在流程定义中在任务结点的 assignee 固定设置任务负责人,在流程定义时将参与者固定设置 在.bpmn 文件中,如果临时任务负责人变更则需要修改流程定义,系统可扩展性差。 针对这种情况可以给任务设置多个候选人,可以从候选人中选择参与者来完成任务。

    设置任务候选人

    在流程图中任务节点的配置中设置 candidate-users(候选人),多个候选人之间用逗号分开。 
    

    在这里插入图片描述
    在这里插入图片描述
    我们可以看到部门经理的审核人已经设置为 zhangsan,lishi 这样的一组候选人,可以使用 activiti:candiateUsers=”用户1,用户 2,用户 3”的这种方式来实现设置一组候选人

    组任务办理流程
    第一步:查询组任务 指定候选人,查询该候选人当前的待办任务。 候选人不能办理任务。

    第二步:拾取(claim)任务 该组任务的所有候选人都能拾取。 将候选人的组任务,变成个人任务。原来候选人就变成了该任务的负责人。 ***如果拾取后不想办理该任务? 需要将已经拾取的个人任务归还到组里边,将个人任务变成了组任务。

    第三步:查询个人任务 查询方式同个人任务部分,根据 assignee 查询用户负责的个人任务。

    第四步:办理个人任务

    1. 部署

    
        /**
         * 1.部署流程定义
         */
        @Test
        public void deploy() {
            //1.创建ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RepositoryService实例
            RepositoryService repositoryService = processEngine.getRepositoryService();
    
            //3.进行部署
            Deployment deployment = repositoryService.createDeployment()
                    .addClasspathResource("diagram/holiday5.bpmn")  //添加bpmn资源
                    .name("请假申请单流程")
                    .deploy();
    
            //4.输出部署的一些信息
            System.out.println(deployment.getName());
            System.out.println(deployment.getId());
        }
    

    2. 启动流程实例

        /**
         * 2.启动流程实例
         */
        @Test
        public void startProcessInstance() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RunService对象
            RuntimeService runtimeService = processEngine.getRuntimeService();
    
            //3.创建流程实例  流程定义的key需要知道 holiday
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_1");
    
    
            //4.输出实例的相关信息
            System.out.println("流程定义ID" + processInstance.getProcessDefinitionId());//holiday:1:4
            System.out.println("流程实例ID" + processInstance.getId());//2501
        }
    
    

    3.填写请假单的任务要执行完成

        /**
         * 3.填写请假单的任务要执行完成
         */
        @Test
        public void complete1() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService对象
            TaskService taskService = processEngine.getTaskService();
    
            //3.查询当前用户的任务
            Task task = taskService.createTaskQuery()
                    .processDefinitionKey("myProcess_1")
                    .taskAssignee("xiaozhang")
                    .singleResult();
    
            //4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
            if (task != null) {
                taskService.complete(task.getId());
                System.out.println("用户任务执行完毕...");
            }
    
    
            //5.输出任务的id
            System.out.println(task.getId());
        }
    

    4.查询候选用户的组任务

        /**
         * 4.查询候选用户的组任务
         */
        @Test
        public void queryGroup() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService对象
            TaskService taskService = processEngine.getTaskService();
    
            //3.设置一些参数,流程定义的key,候选用户
            String key = "myProcess_1";
            String candidate_users = "zhangsan";
    
            //4.执行查询
            List<Task> list = taskService.createTaskQuery()
                    .processDefinitionKey(key)
                    .taskCandidateUser(candidate_users)//设置候选用户
                    .list();
            //5.输出
            for (Task task : list) {
                System.out.println(task.getProcessInstanceId());//2501 实例id
                System.out.println(task.getId());//5002  任务id
                System.out.println(task.getName());//部门经理审核
                System.out.println(task.getAssignee());//为null,说明当前的zhangsan只是一个候选人,并不是任务的执行人
            }
        }
    
    

    在这里插入图片描述

    5. 拾取任务

    候选人员拾取组任务后该任务变为自己的个人任务。
    说明:即使该用户不是候选人也能拾取,建议拾取时校验是否有资格 组任务拾取后,该任务已有负责人,通过候选人将查询不到该任务

        /**
         * 5.测试zhangsan用户,来拾取组任务
         * 抽取任务的过程就是将候选用户转化为真正任务的负责人(让任务的assignee有值)
         * 说明:即使该用户不是候选人也能拾取,建议拾取时校验是否有资格 组任务拾取后,该任务已有负责人,通过候选人将查询不到该任务
         */
        @Test
        public void claim() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService对象
            TaskService taskService = processEngine.getTaskService();
    
            //3.设置一些参数,流程定义的key,候选用户
            String key = "myProcess_1";
            String candidate_users = "zhangsan";
    
            //4.执行查询
            Task task = taskService.createTaskQuery()
                    .processDefinitionKey(key)
                    .taskCandidateUser(candidate_users)//设置候选用户
                    .singleResult();
            if (task != null) {
                taskService.claim(task.getId(), candidate_users);//第一个参数任务ID,第二个参数为具体的候选用户名
                System.out.println("任务拾取完毕!");
            }
        }
    

    在这里插入图片描述

    6. 当前用户查看自己的任务

        /**
         * 6.当前的用户查询自己的任务
         */
        @Test
        public void queryTask() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService对象
            TaskService taskService = processEngine.getTaskService();
    
            //3.设置一些参数,流程定义的key,用户
            String key = "myProcess_1";
            String assignee = "zhangsan";
    
            //4.执行查询
            List<Task> list = taskService.createTaskQuery()
                    .processDefinitionKey(key)
                    .taskAssignee(assignee)  //设置任务的负责人
                    .list();
            //5.输出
            for (Task task : list) {
                System.out.println(task.getProcessInstanceId());//2501
                System.out.println(task.getId());//5002
                System.out.println(task.getName());//部门经理审核
                System.out.println(task.getAssignee());// zhangsan  拾取任务之后具有任务的执行人
            }
        }
    
    

    7. 当前用户完成自己的任务

    说明:建议完成任务前校验该用户是否是该任务的负责人。

        /**
         * 7.当前用户完成自己的任务
         */
        @Test
        public void completeMyTask() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService对象
            TaskService taskService = processEngine.getTaskService();
    
            //3.设置一些参数,流程定义的key,用户
            String key = "myProcess_1";
            String assignee = "lisi";
    
            //4.执行查询
            Task task = taskService.createTaskQuery()
                    .processDefinitionKey(key)
                    .taskAssignee(assignee)  //设置任务的负责人
                    .singleResult();
            //5.执行当前的任务
            if (task != null) {
                taskService.complete(task.getId());
                System.out.println("任务执行完毕!");
            }
    
        }
    

    8.归还任务和任务交接

    如果个人不想办理该组任务,可以归还组任务,归还后该用户不再是该任务的负责人
    任务交接,任务负责人将任务交给其它候选人办理该任务
    说明:建议归还任务前校验该用户是否是该任务的负责人 也可以通过 setAssignee 方法将任务委托给其它用户负责,注意被委托的用户可以不是候选人(建议 不要这样使用)

        /**
         * 8.任务交接,前提要保证当前用户是这个任务的负责人,这时候他才可以有权限去将任务交接给其他候选人
         */
        @Test
        public void main() {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到TaskService对象
            TaskService taskService = processEngine.getTaskService();
    
            //3.设置一些参数,流程定义的key,用户
            String key = "myProcess_1";
            String assignee = "zhangsan";
    
            //4.执行查询
            Task task = taskService.createTaskQuery()
                    .processDefinitionKey(key)
                    .taskAssignee(assignee)  //设置任务的负责人
                    .singleResult();
            //5.判断是否有这个任务
            if (task != null) {
                //taskService.setAssignee(task.getId(), null);//归还为组任务
                taskService.setAssignee(task.getId(), "lisi");//交接任务为lisi  ,交接任务就是一个候选人拾取用户的过程
                System.out.println("交接任务完成~!");
            }
        }
    
    

    总结

    1. 即使该用户不是候选人也能拾取,建议拾取时校验是否有资格 组任务拾取后,该任务已有负责人,通过候选人将查询不到该任务
    2. 建议完成任务前校验该用户是否是该任务的负责人。
    3. 建议归还任务前校验该用户是否是该任务的负责人 也可以通过 setAssignee 方法将任务委托给其它用户负责,注意被委托的用户可以不是候选人(建议 不要这样使用)

    在这里插入图片描述

    网关

    1.未使用网关

    在这里插入图片描述

    部门经理审批完成后会发现数据库中两个任务都存在了这样就会出现问题

    在这里插入图片描述

    2. 排他网关

    排他网关(也叫异或(XOR)网关,或叫基于数据的排他网关),用来在流程中实现决策。 当流程 执行到这个网关,所有分支都会判断条件是否为 true,如果为 true则执行该分支, 注意,排他网关只会选择一个为 true 的分支执行。 (即使有两个分支条件都为 true,排他网关也会只 选择一条分支去执行) 如果都为false 抛出异常

    为什么要用排他网关? 不用排他网关也可以实现分支,如下图:
    在这里插入图片描述

    上图中,在连线的 condition 条件上设置分支条件。 缺点: 如果条件都不满足,不使用排他网关,流程就结束了(是异常结束)。

    如果 使用排他网关决定分支的走向,如下
    在这里插入图片描述

    如果从网关出去的线所有条件都不满足则系统抛出异常。 org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway ‘exclusivegateway1’ could be selected for continuing the process at org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehav ior.leave(ExclusiveGatewayActivityBehavior.java:85)

    说明 :经过排他网关必须要有一条且只有一条分支走。
    在这里插入图片描述

    3. 并行网关

    并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进 入和外出顺序流的:

    • fork 分支: 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
    • join 汇聚: 所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通 过汇聚网关。

    注意,如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。 这时, 网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。

    与其他网关的主要区别是,并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略。

    例子:
    在这里插入图片描述
    说明:

    财务结算和入库是两个 execution 分支,在 act_ru_execution 表有两条记录分别是财务结算和入库, act_ru_execution 还有一条记录表示该流程实例。 待财务结算和入库任务全部完成,在汇聚点汇聚,通过 parallelGateway 并行网关。 并行网关在业务应用中常用于会签任务,会签任务即多个参与者共同办理的任务。

    在这里插入图片描述

    测试:
    当执行到并行网关数据库跟踪如下:

    当前任务表:SELECT * FROM act_ru_task #当前任务表
    在这里插入图片描述
    上图中:有两个(多个)任务当前执行。

    通过流程实例执行表:SELECT * FROM act_ru_execution #流程实例的执行表
    在这里插入图片描述
    上图中,说明当前流程实例有多个分支(两个)在运行。

    对并行任务的执行: 并行任务执行不分前后,由任务的负责人去执行即可。

    当完成并任务中一个任务后: 已完成的任务在当前任务表 act_ru_task_已被删除。 在流程实例执行表:SELECT * FROM act_ru_execution 有中多个分支存在且有并行网关的汇聚结点。

    在这里插入图片描述

    有并行网关的汇聚结点:说明有一个分支已经到汇聚,等待其它的分支到达。

    当所有分支任务都完成,都到达汇聚结点后: 流程实例执行表:SELECT * FROM act_ru_execution,执行流程实例不存在,说明流程执行结束。

    总结:所有分支到达汇聚结点,并行网关执行完成

    4. 包含网关

    包含网关可以看做是排他网关和并行网关的结合体。 和排他网关一样,你可以在外出顺序流上 定义条件,包含网关会解析它们。 但是主要的区别是包含网关可以选择多于一条顺序流,这和并行 网关一样。 包含网关的功能是基于进入和外出顺序流的:

    • 分支:
      所有外出顺序流的条件都会被解析,结果为true 的顺序流会以并行方式继续执行, 会为每个顺序流创建一个分支。
    • 汇聚:
      所有并行分支到达包含网关,会进入等待状态, 直到每个包含流程 token 的进入顺序流的分支都 到达。 这是与并行网关的最大不同。换句话说,包含网关只会等待被选中执行了的进入顺序流。 在 汇聚之后,流程会穿过包含网关继续执行

    流程定义
    在这里插入图片描述
    员工类型:

    通过流程变量 userType 来表示,如果等于 1 表示普通员工,如果等于 2表示领导 
    

    在这里插入图片描述

    注意:通过包含网关的每个分支的连线上设置 condition 条件。

    测试

    如果包含网关设置的条件中,流程变量不存在,报错; org.activiti.engine.ActivitiException: Unknown property used in expression: ${userType==‘1’ || userType==‘2’} 需要在流程启动时设置流程变量 userType

    当执行到包含网关:

    流程实例执行表:SELECT * FROM act_ru_execution

    删除

    删除实例

    processEngine.getRuntimeService().deleteProcessInstance(“25001”,“测试下一个”);

    参数介绍:
    参数1:实例id
    参数2:删除原因
    删除实例会也会级联删除当前实例所有的运行的任务 在历史任务中可以查看删除原因

    删除部署

     String examine = repositoryService.createProcessDefinitionQuery().processDefinitionKey("examine").singleResult().getDeploymentId();
     repositoryService.deleteDeployment(examine, true);
    

    参数介绍
    参数1:部署id
    参数2:默认值为false 级联删除 如果为true会级联删除跟当前部署图有关的所有信息(包含历史实例 历史任务 参与者 和当前的)
    如果为false 任务表还存在当前部署的任务 则会抛出异常
    Cannot delete or update a parent row: a foreign key constraint fails (activiti.act_ru_execution, CONSTRAINT ACT_FK_EXE_PROCDEF FOREIGN KEY (PROC_DEF_ID_) REFERENCES act_re_procdef (ID_))

    在这里插入图片描述
    在这里插入图片描述

    删除任务

        processEngine.getTaskService().deleteTask(taskid, true);
    

    运行中的任务无法进行删除 会抛出异常
    org.activiti.engine.ActivitiException: The task cannot be deleted because is part of a running process

    在这里插入图片描述

  • 相关阅读:
    ubuntu14.04安装chromium以及flash插件
    linux fuser的使用
    对max_allowed_packet这个参数的误解
    Linux hostname主机名配置文件与文件 /etc/hosts解析(copy来的,原作者看到了别打我)
    三个参数,对mysql存储限制的影响
    唉,没来这里好久了,也意味着我这一年多来没干什么正事儿,是回归的时候了!(简单谈谈爬虫的解析器)
    STM32 宏定义翻转端口
    ascii码表
    平均值算法
    stm8 16M晶振下精确软件延时
  • 原文地址:https://www.cnblogs.com/idcode/p/14551359.html
Copyright © 2020-2023  润新知