工作流子流程和多实例开发

在项目中有子流程和多实例的需求,总结如下:
一、子流程

子流程分为两种:

  1. CallActivity(调用任务)
  2. SubProcess(子流程)

由于调用任务能将子任务分离开来,能够分别显示单独的流程图,实际在项目中用到更多的是调用任务,这里我们主要介绍调用任务:
调用任务的流程图如下:
父流程
父流程图1
子流程
子流程图2

图1中我们有一个普通的任务task1和一个调用任务,图2是图1调用任务要调用的流程,只有一个普通的任务sonTask,图中这个任务下面有三道竖线说明它是多实例任务,我们一会儿再介绍,先不管它。
图中的主要属性如下:

  • 父流程:{Id:parentProcess};
  • task1:{Id:usertask1,Assignee:parent};
  • 调用任务:{Id:callactivity1,Called element:sunProcess}
  • 子流程:{Id:sunProcess};
  • sonTask:{Id:usertask2,Assignee:son};

可以看到调用任务的配置很简单,只需要将Called element的属性值修改为需要调用的子流程id即可。
部署时父子流程都需要部署:

/**
     * 部署流程定义(classpath)
     */
    @Test
    public void deploymentProcessDefinition() {
        Deployment dp = pe.getRepositoryService().createDeployment()
                                    .name("父子流程")
                                    .addClasspathResource("diagrams/Parent.bpmn")
                                    .addClasspathResource("diagrams/Parent.png")
                                    .addClasspathResource("diagrams/Son.bpmn")
                                    .addClasspathResource("diagrams/Son.png")
                                    .deploy();
        System.out.println("部署ID:"+dp.getId());
        System.out.println("部署名称:"+dp.getName());
    }

启动流程实例时只启动父流程:

/**
     * 启动流程实例
     */
    @Test
    public void startProcessInstance() {
        String processDefinitionKey = "parentProcess";
        ProcessInstance pi = pe.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey);
        System.out.println("流程实例ID:"+pi.getProcessInstanceId());
        System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
    }

接下来把流程跑通一遍,我们来看一下act_hi_actinst表的数据:
act_hi_actinst表数据

当完成usertask1之后,任务节点到达了callactivity,表中的CALL_PROC_INST_ID_字段代表了要调用哪个流程,这时直接开启了proc_inst_id_为5003的子流程,完成了startevent1节点,到达了usertask2任务,当完成usertask2之后,子流程结束,父流程结束,整个流程执行完毕。

这是最简单的调用任务,但是如果我们在父流程中设置了流程变量,我们就需要将流程变量传到子流程当中,这时就需要配置callactivity的Input parameters和Output parameters属性:
这里写图片描述
其中Source是父流程的流程变量名称,Target是子流程的流程变量名称,也就是说子流程和父流程中对应同一个流程变量的名字可以不同,我们映射一下就可以了。同理Output parameters配置的是从子流程中返回的流程变量和父流程的映射关系。如果我们的流程变量是javabean的话,我们就用EL表达式来配置Source expression和Target expression。
我们在父流程中设置一个流程变量name,用来动态的设置子流程usertask2任务的办理人,我们需要将Source和Target属性都设置为name,将usertask2的Assignee属性设置为${name},我们再跑通一次流程,观察一下表中的变化:
act_ru_variable
act_ru_variable表1
act_hi_actinst
act_hi_actinst表2

我们在启动父流程的时候设置了流程变量name:


    /**
     * 启动流程实例
     */
    @Test
    public void startProcessInstance() {
        String processDefinitionKey = "parentProcess";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "xiaowang");
        ProcessInstance pi = pe.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey,map);
        System.out.println("流程实例ID:"+pi.getProcessInstanceId());
        System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
    }

我们看表一中父流程和子流程都有一个叫name的流程变量,说明流程变量传进了子流程,同时子流程的usertask2的办理人设置成了”xiaowang”,完成了动态设置办理人的需求。outputparameter的设置同理,大家可以自行测试。

这里还有一个建议,如果有调用任务的需求,我们在开发中最好用javabean类型的流程变量来存储业务数据,否则我们在inputparameter和outputparameter中就需要手动设置所有的流程变量,很麻烦,还需要去代码中看我到底设置了哪些流程变量。

二、多实例
单独的多实例比较简单,只是配置任务的几个属性就可以了。如下:
多实例配置

1.Sequential是设置多实例任务是同步执行还是按照顺序执行,”false”为同步执行;
2.Collection是多实例的核心属性,值为集合类型的流程变量名称,这里我在启动流程实例时设置了一个类型为List的流程变量,名称为names,代码如下:

/**
     * 启动流程实例
     */
    @Test
    public void startProcessInstance() {
        String processDefinitionKey = "sunProcess";
        Map<String, Object> map = new HashMap<String, Object>();
        List<String> names = new ArrayList<String>();
        names.add("xiaowang");
        names.add("xiaoli");
        names.add("xiaozhang");
        map.put("names", names);
        ProcessInstance pi = pe.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey,map);
        System.out.println("流程实例ID:"+pi.getProcessInstanceId());
        System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
    }

3.Element variable为Collection中每一个元素的名称,这个名称是自己定义的,当我们要使用多实例集合中的每一个元素时,总要有个名字。我们在动态设置每一个实例执行对象的Assignee时,用到了这个name:
这里写图片描述
这样的话,每一个实例就可以根据我们程序中List的每一个元素值来动态设置,我们看一下表中的执行结果:
act_hi_actinst
act_hi_actinst表
这里我们可以看到同时执行的usertask2有三个,分别动态赋予了不同的Assignee,并且他们的execution_id是不同的,所以在多实例或者有分支和并行的流程中,我们能够看出流程实例id(proc_inst_id_)和执行对象id(execution_id_)其实是不同的。

不过很多时候多实例流程不只需要动态配置一个assignee属性,这种时候我们需要将流程变量List中的元素改成javabean对象,在配置assignee时用对象的属性来配置:
这里写图片描述

这里需要补充的是所有的多实例跑完才会执行下一步流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值