• 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 容器的一个 beanfindManagerForEmployee 是该 bean 的一个方法,emp activiti
    流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中


    表达式支持解析基础类型、 beanlistarray 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 在管理工作流时根据管理需要而设置的变量

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


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


    设置流程变量

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

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

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

    uel为true,决定流程走向

    使用 Global 变量控制流程

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

    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 的分支执行 

    部署流程定义

    //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 汇聚:
    所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通
    过汇聚网关

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

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

    包含网关

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

     分支

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

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

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

     

     完

  • 相关阅读:
    [noip2018]day1
    [CF1110d]JONGMAH
    BZOJ 2733 [HNOI2012]永无乡
    BZOJ 3123 [SDOI2013] 森林
    Nowcoder 练习赛26E 树上路径
    Luogu 2575 高手过招-SG函数
    BZOJ 1123[POI2008]BLO-Tarjan
    Nowcoder OI赛制测试2 F 假的数学题
    Luogu 2467[SDOI2010]地精部落
    Luogu 2216[HAOI2007]理想的正方形
  • 原文地址:https://www.cnblogs.com/quyangyang/p/11345867.html
Copyright © 2020-2023  润新知