activiti05

什么是流程实例

参与者(可以是用户也可以是程序)按照流程定义内容发起一个流程,这就是一个流程实例。是动
态的。

 

流程定义部署在 activiti 后,就可以在系统中通过 activiti 去管理该流程的执行,执行流程表示流
程的一次执行。
多个用户可同时执行该流程,每个执行互不影响,每个执行是单独的流程实例

 

流程实例的部署与启动

 1 /**
 2  * 流程变量的测试---新的请假流程定义的部署
 3  * 1.得到ProcessEngine
 4  * 2.得到ReposuitoryService对象
 5  * 3.实现部署
 6  *
 7  */
 8 
 9     public static void main(String[] args) {
10 /*      ProcessEngine ProcessEngine = ProcessEngines.getDefaultProcessEngine();
11         RepositoryService repositoryService = ProcessEngine.getRepositoryService();
12         Deployment deployment = repositoryService.createDeployment()
13         .addClasspathResource("diagram/holiday4.bpmn")
14         .addClasspathResource("diagram/holiday4.png").name("请假流程-流程变量")
15         .deploy();
16         System.out.println(deployment.getId());
17         System.out.println(deployment.getName());*/


18 //流程实例的启动
      ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();



ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");
System.out.println("流程定义ID"+processInstance.getProcessDefinitionId()); //92503
System.out.println("流程实例ID"+processInstance.getId());
19 

 

BussinessKey 业务标识

 

启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey

Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业
务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据

 1 /**
 2  * 添加bussinessKey
 3  * 1.得到ProcenessEngine
 4  * 2.得到RuntimeService
 5  * 3.管理流程实例,指定业务标识bussinessKey
 6  *    ---params 流程定义的key ,业务标识bussinessKey
 7  * 4.输出processInstance属性
 8  *
 9  * 本质:act_ru_execution表的bussinessKey要存入标识
10  *
11  */
12 
13 
14     public static void main(String[] args) {
15         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
16         RuntimeService runtimeService = processEngine.getRuntimeService();
17         ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");
18 
19         System.out.println(processInstance.getBusinessKey());
20     }

 

挂起、激活流程实例

由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行 

全部流程实例挂起

 1  /**
 2      * 全部流程的挂起和激活
 3      * 1.得到ProcessEngine对象
 4      * 2.得到RepositoryService
 5      * 3.查询流程定义对象
 6      * 4.得到当前流程定义是否为暂停状态
 7      * 5.判断
 8      */
 9     public static void main(String[] args) {
10         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
11         RepositoryService repositoryService = processEngine.getRepositoryService();
12         ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("请假流程").singleResult();
13         boolean suspended = processDefinition.isSuspended();
14 
15         String processDefinitionId = processDefinition.getId();
16 
17         if (suspended){
18             repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
19             System.out.println("流程定义:"+processDefinitionId+"激活");
20         }else {
21             repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
22             System.out.println("流程定义:"+processDefinitionId+"挂起");
23         }
24 
25 
26 
27     }

 

 

单个流程执行挂起操作,某个流程实例挂起则此流程不再继续执行

   /** 1.得到processEngine
     * 2.获取RuntimeService
     * 3.根据流程实例id查询流程实例
     * 4.判段
     */
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId("35001").singleResult();   //act_ru_execution
        boolean suspended = processInstance.isSuspended();
        String processInstanceId = processInstance.getId();
        if (suspended){
            runtimeService.activateProcessInstanceById(processInstanceId);;
            System.out.println("流程定义"+processInstanceId+"激活");
        }else {
            runtimeService.suspendProcessInstanceById(processInstanceId);
            System.out.println("流程定义"+processInstanceId+"挂起");
        }

 



个人任务

 

 

固定分配    

Assigneee:任务负责人

表达式分配     

 UEL 表达式     activiti 支持两个 UEL 表达式: UEL-value 和 UEL-method,   assignee 这个变量是 activiti 的一个流程变量

${ldapService.findManagerForEmployee(emp)}
ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti
流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中


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


使用流程变量分配任务
 

start  -》 填写请假申请单 -》部门经理审批 -》总经理审批 -》end

设部门经理审批的Assignee 为 ${assignee}

 

1.自动流程实例

/**
 *自动流程实例
 * 1.得到ProcessEngine
 * 2.得到RuntimeService
 * 3.设置assignee的取值,用户可以在界面上设置流程执行人
 * 4.启动流程实例,同时设置流程定义的assignee的值
 * 5.输出
 */

    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String,Object> map = new HashMap<>();
        map.put("assignee","zhangsan");


        ProcessInstance processInstance =
                runtimeService.startProcessInstanceByKey("holiday2", map);

    }

 

监听器分配
Task Listeners

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

定义任务监听类,且类必须实现 org.activiti.engine.delegate.TaskListener 接口

 

流程变量

流程变量就是 activiti 在管理工作流时根据管理需要而设置的变量

activiti05

 

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


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


设置流程变量

通过UEL表达式使用流程变量

1.在assignee处设置uel表达式,表达式的值为任务的负责人

2.在连线上设置uel表达式,决定流程走向

uel为true,决定流程走向

 

使用 Global 变量控制流程

需求:员工创建请假申请单,由部门经理审核,部门经理审核通过后请假 3 天及以下由人事经理直接
审核, 3 天以上先由总经理审核,总经理审核通过再由人事经理存档

activiti05

Holiday

 1 public class Holiday implements Serializable {
 2 
 3     private Integer id;
 4     private String holidayName;
 5     private Date beginDate;
 6     private Date endDate;
 7     private Float num;
 8     private String reason;
 9     private String type;
10    
11     //getter
12     //setter    
13   
16 
17 }

 

 

启动流程时设置 

在启动流程时设置流程变量,变量的作用域是整个流程实例 

/**
 * 流程变量的测试---新的请假流程定义的部署
 * 1.得到ProcessEngine
 * 2.得到ReposuitoryService对象
 * 3.实现部署
 *
 */

    public static void main(String[] args) {
/*        ProcessEngine ProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = ProcessEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
        .addClasspathResource("diagram/holiday4.bpmn")
        .addClasspathResource("diagram/holiday4.png").name("请假流程-流程变量")
        .deploy();
        System.out.println(deployment.getId());
        System.out.println(deployment.getName());*/


/**
 * 启动流程实例,设置流程变量
 * 1.得到ProcessEngine
 * 2.得到RuntimeService
 * 3.流程定义的key myProcess_1
 * act_ge_bytearray
 * act_ru_variable
 */
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RuntimeService runtimeService = processEngine.getRuntimeService();

        String key = "myProcess_1";
        Map<String,Object> map = new HashMap<>();
        Holiday holiday = new Holiday();
        holiday.setNum(1F);
        map.put("holiday",holiday);

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, map);

        System.out.println(processInstance.getProcessDefinitionId());


    }

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

 

 任务办理时设置

 1     public static void main(String[] args) {
 2 
 3         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 4         TaskService taskService = processEngine.getTaskService();
 5         String key = "myProcess_1";
 6         Task task = taskService.createTaskQuery().processDefinitionKey(key)
 7                 .taskAssignee("zhangsan").singleResult();
 8 
 9         Map<String,Object> map = new HashMap<>();
10 
11         Holiday holiday = new Holiday();
12         holiday.setNum(5F);
13 
14         map.put("holiday",holiday);
15         if (task != null){
16             taskService.complete(task.getId(),map);
17             System.out.println("任务执行完成");
18         }
19     }

 

 

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

 1 /**
 2  *通过流程实例ID设置全局变量
 3  *1.得到ProcessEngine
 4  * 2.得到RuntimeService
 5  * 3.流程定义的key问题
 6  * 4.通过实例id,来设置流程变量
 7  *          参数:流程实例的id,流程变量名,流程变量名所对应的值
 8  * 5.
 9  */
10 
11     
12    /*  //流程实例的定义
13    public static void main(String[] args) {
14 
15         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
16 
17         RuntimeService runtimeService = processEngine.getRuntimeService();
18 
19         String key = "myProcess_1";
20 
21 
22         ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
23 
24         System.out.println(processInstance.getProcessDefinitionId());
25         System.out.println(processInstance.getId());   //流程实例的id  70001
26 
27 
28         }*/
29 
30     public static void main(String[] args) {
31 
32         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
33 
34         RuntimeService runtimeService = processEngine.getRuntimeService();
35 
36         String key = "myProcess_1";
37         Holiday holiday = new Holiday();
38         holiday.setNum(5F);
39 
40         runtimeService.setVariable("70001","holiday",holiday);
41 
42 
43     }

executionId 必须当前未结束 流程实例的执行 id,通常此 id 设置流程实例 的 id。

 

4.通过当前任务设置

 

gloal 变量

taskService.setVariblesLocal(......)

 

 

组任务

设置多个候选人,可以从候选人中选择参与者来完成任务

 

使用activiti:candiateUsers=”用户 1,用户 2,用户 3”的这种方式来实现设置一组候选人

 

组任务的办理流程

1.查询组任务

2.拾取(claim)任务

3.查询个人任务

4.办理个人任务

 

场景

start -> 填写请假单 -》部门经理审批(Candidate User : zhangsa,lisi)   -》总经理

 

1.部署流程定义 2.启动流程实例

用户组查询任务

 1  /**
 2          * 1.得到ProcessEngine
 3          * 2.得到TaskService
 4          * 3.设置一些参数,流程
 5          * 4.执行查询
 6          */
 7      ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 8         TaskService taskService = processEngine.getTaskService();
 9 
10         String key = "myProcess_1";
11         String candidate_users = "zhangsan";
12         List<Task> list = taskService.createTaskQuery()
13                 .processDefinitionKey(key)
14                 .taskCandidateUser(candidate_users) //设置候选用户
15                 .list();
16 
17         for (Task task : list){
18             System.out.println(task.getProcessInstanceId());
19             System.out.println(task.getId());
20             System.out.println(task.getName());
21             System.out.println(task.getAssignee());
22         }

 

用户拾取任务

 //拾取任务的过程就是将候选选用户转化为真正任务的负责人(让任务的assignee有值)
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();

        String key = "myProcess_1";
        String candidate_users = "zhangsan";
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskCandidateUser(candidate_users)
                .singleResult();
        if (task != null){
            taskService.claim(task.getId(),candidate_users);//(参数任务的ID,具体的候选用户名)
            System.out.println("任务拾取完毕");
        }

 

用户查询自己的任务

//当前的用户查询自己的任务
      ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();

        String key = "myProcess_1";
        String assignee = "zhangsan";
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assignee)
                .list();


        for (Task task : list){
            System.out.println(task.getProcessInstanceId());
            System.out.println(task.getId());
            System.out.println(task.getName());
            System.out.println(task.getAssignee());
        }

 

用户办理个人任务

 1  ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 2         TaskService taskService = processEngine.getTaskService();
 3         String key = "myProcess_1";
 4         String assignee="zhangsan";
 5         Task task = taskService.createTaskQuery()
 6                 .processDefinitionKey(key)
 7                 .taskAssignee(assignee)  //设置任务的负责人  
 8                 .singleResult();
 9 
10         if (task != null){
11             taskService.complete(task.getId());
12             System.out.println("任务执行完毕!");
13         }

 

归还组任务

 1   TaskService taskService = processEngine.getTaskService();
 2 // 当前待办任务
 3   String taskId = "6004";
 4 // 任务负责人
 5   String userId = "zhangsan2";
 6 // 校验userId是否是taskId的负责人,如果是负责人才可以归还组任务
 7   Task task = taskService.createTaskQuery().taskId(taskId)
 8   .taskAssignee(userId).singleResult();
 9   if (task != null) {
10 // 如果设置为null,归还组任务,该 任务没有负责人
11   taskService.setAssignee(taskId, null);

 

任务交接

任务交接,任务负责人将任务交给其它候选人办理该任务

 

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

 

 

网关

排他网关(也叫异或(XOR)网关,或叫基于数据的排他网关),用来在流程中实现决策。 当流程
执行到这个网关,所有分支都会判断条件是否为 true,如果为 true 则执行该分支

在condition上设置条件

排他网关只会选择一个为 true 的分支执行 

activiti05

部署流程定义

//1.部署流程定义
 public static void main(String[] args) {
        //1.创建ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RepositoryService实例
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3.进行部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("diagram/day05/holiday5.bpmn")  //添加bpmn资源
                //.addClasspathResource("diagram/holiday5.png")
                .name("请假申请单流程")
                .deploy();

        //4.输出部署的一些信息
        System.out.println(deployment.getName());
        System.out.println(deployment.getId());
    }

启动流程实例

 1 public static void main(String[] args) {
 2             //1.得到ProcessEngine对象
 3             ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 4 
 5             //2.得到RunService对象
 6             RuntimeService runtimeService = processEngine.getRuntimeService();
 7 
 8         Holiday holiday = new Holiday();
 9         holiday.setNum(5F);
10         Map<String,Object> map = new HashMap<>();
11         map.put("holiday",holiday);//流程变量赋值
12 
13             //3.创建流程实例  流程定义的key需要知道 holiday
14             ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayExclusive",map);
15 
16 
17             //4.输出实例的相关信息
18             System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4
19             System.out.println("流程实例ID"+processInstance.getId());//2501
20     }

 

依次执行任务

public static void main(String[] args) {
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.查询当前用户的任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayExclusive")
                .taskAssignee("zhangsan")
                .singleResult();

        //4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
        if(task!=null){
            taskService.complete(task.getId());
            System.out.println("用户任务执行完毕...");
        }

 

 

 并行网关

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

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

 并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略

activiti05

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

 

 

包含网关

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

 分支

所有外出顺序流的条件都会被解析,结果为 true 的顺序流会以并行方式继续执行, 会为每个顺序流 创建一个分支。
汇聚

所有并行分支到达包含网关,会进入等待状态, 直到每个包含流程 token 的进入顺序流的分支都到达。 
activiti05

先走到汇聚结点的分支,要等待其它分支走到汇聚。
等所有分支走到汇聚,包含网关就执行完成。包含网关执行完成,分支和汇聚就从act_ru_execution删除

 

 

 

 

 

 完

 

上一篇:activiti入门学习之单机Demo演示


下一篇:flowable实战(三)flowable流程实例管理接口