【activiti 入门】activiti6.0之并行网关

首先是环境搭建可参考之前的博客,而且有具体demo提供下载  https://download.csdn.net/download/qq_33333654/11790823

demo中仅涵盖了排他网关的实例。

 

接下来准备绘制流程图:

【activiti 入门】activiti6.0之并行网关_第1张图片

具体的xml代码如下:

 



  
    
    
    
    
    
    
    
    
    
    
    
    
    
      
    
    
      
    
    
    
    
      
    
    
      
    
    
    
    
      
    
  
  
    
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
          
        
      
      
        
        
        
          
        
      
      
        
        
        
          
        
      
      
        
        
        
        
          
        
      
      
        
        
        
        
          
        
      
      
        
        
        
        
          
        
      
      
        
        
        
        
          
        
      
      
        
        
        
          
        
      
      
        
        
        
          
        
      
      
        
        
        
          
        
      
      
        
        
        
          
        
      
      
        
        
        
          
        
      
    
  

 该实例图中有排他网关和并行网关,避免理解错误。菱形中间带X的是排他网关,带+号的是并行网关。

所谓并行其实就是java的&&。图片中只有上下两条路全部通过并行网关才会放行到最终审批,否则任意一条不通过,都会处于等待状态。例如:审批B通过了,但是审批C驳回了,那么并行网关是不会通过的。

接下来上具体操作代码:

准备下工具类和连线的限制条件所需的实体bean,实体bean会存放到act数据的全局变量中(act_ru_variable),可以通过这个变量操作流程。

工具类:

package com.example.demo.utils;

import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @ProjectName: demo
 * @Package: com.example.demo.utils
 * @ClassName: ActivitiUtil
 * @Author: MC
 * @Description: ${description}
 * @Date: 2019/9/19 0019 18:17
 * @Version: 1.0
 */
@Service
public class ActivitiUtil {
    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private RuntimeService runtimeService ;

    @Autowired
    private TaskService taskService ;

    @Autowired
    private RepositoryService repositoryService;

    /**
     * @Method 部署流程
     * @Author MC

     * @Return
     * @Date 2019/9/19 0019 18:34
     */
    public void deploy(String filePath){
        if(!StringUtils.isEmpty(filePath)){
            repositoryService.createDeployment()
                    .addClasspathResource(filePath)
                    .deploy();
        }
    }

    /**
     * @Method 启动流程
     * @Author MC

     * @Return
     * @Date 2019/9/19 0019 18:35
     */
    public Map start(Map map ,String processId){
        ProcessInstance leave1 = runtimeService.startProcessInstanceByKey(processId, map);
        String processDefinitionId = leave1.getProcessDefinitionId();
        System.out.print("============processDefinitionId:" + processDefinitionId);//流程定义的ID
        System.out.print("============processInstanceId:" + leave1.getId());//流程实例的ID
        Map resultMap = new HashMap<>();
        resultMap.put("result",leave1);
        resultMap.put("processDefinitionId",processDefinitionId);
        resultMap.put("processInstanceId",leave1.getId());
        return resultMap;
    }

    /**
     * @Method 根据流程实例ID和用户ID查询任务ID
     * @Author MC
     用户ID必须设置为Assignee
     * @Return
     * @Date 2019/9/19 0019 19:01
     */
    public String getTaskIdByAssignee( String processInstanceId, String userId){
        TaskService taskService = processEngine.getTaskService();//获取任务的Service,设置和获取流程变量
        //查询当前办理人的任务ID
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskAssignee(userId)//任务办理人
                .singleResult();

        return  task.getId();
    }

    /**
     * @Method 根据流程实例ID和userTask标签体设置的ID获取当前任务对象
     * @Author MC

     * @Return
     * @Date 2019/9/24 0024 9:54
     */
    public String getTaskIdByDefinitionKey( String processInstanceId, String defKey){
        TaskService taskService = processEngine.getTaskService();//获取任务的Service,设置和获取流程变量
        //查询当前办理人的任务ID
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskDefinitionKey(defKey)//userTask标签体的id
                .singleResult();

        return  task.getId();
    }

    /**
     * @Method 获取流程实例列表
     * @Author MC

     * @Return
     * @Date 2019/9/19 0019 18:32
     */
    public List queryProcessInstanceAllList(String processDefinitionKey){
        return runtimeService
                .createProcessInstanceQuery().processDefinitionKey(processDefinitionKey)
                .list();
    }


    /**
     * @Method 根据assignee来查询用户
     * @Author MC

     * @Return
     * @Date 2019/9/19 0019 18:29
     */
    public Task queryTask(String assignee) {
        //startProcessInstance();
        // taskService.createTaskQuery().taskCandidateGroup("sales").singleResult();

        Task task= taskService.createTaskQuery().taskAssignee(assignee).singleResult();
        if(task == null){
            return null;
        }

        System.out.println("审批人为【"+assignee+"】的任务有:任务编号为【" + task.getId() + "】"+ task.getTaskDefinitionKey());
        return task;
    }

    public Task queryTask(String assignee, String processInstanceId) {

        Task task=  taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskAssignee(assignee)//任务办理人
                .singleResult();
        if(task == null){
            return null;
        }

        System.out.println("审批人为【"+assignee+"】的任务有:任务编号为【" + task.getId() + "】"+ task.getTaskDefinitionKey());
        return task;
    }

    /**
     *
     * @param queryType  查询类型1 根据 assignee 查询  2 根据candidateuser查询
     * @param str
     */
    public String getNextNodeId(int queryType,String str) {


        Task task = null;
        if(queryType==1) {
            task = taskService.createTaskQuery().taskAssignee(str).singleResult();
        }else if(queryType==2){
            task = taskService.createTaskQuery().taskCandidateUser(str).singleResult();

        }else if(queryType==3){
            task = taskService.createTaskQuery().taskCandidateGroup(str).singleResult();

        }

//        List list = getNextNode(task.getId());


        if(task==null) {
            return null;
        }

//        for(FlowElement e :list) {
//            //((org.activiti.bpmn.model.UserTask) e)
//        }
        return task.getId();

    }


    /**
     * 获取流程的下一个节点 且要经过规则引擎判断后的节点
     * @param taskId
     * @return
     */
    private List getNextNode(String taskId) {

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(task==null) {
            return null;
        }
        List list = new ArrayList();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();

        //当前活动节点
        String activitiId = processInstance.getActivityId();

        System.out.println("当前节点是【"+activitiId+"】");

        //pmmnModel 遍历节点需要它
        BpmnModel bpmnModel =  repositoryService.getBpmnModel(task.getProcessDefinitionId());

        List processList = bpmnModel.getProcesses();

        //循环多个物理流程
        for(Process process:processList) {

            //返回该流程的所有任务,事件
            Collection cColl = process.getFlowElements();
            //遍历节点
            for(FlowElement f :cColl) {


                //如果改节点是当前节点 者 输出该节点的下一个节点
                if(f.getId().equals(activitiId)) {

                    List  sequenceFlowList = new ArrayList();
                    //通过反射来判断是哪种类型
                    if(f instanceof org.activiti.bpmn.model.StartEvent) {
                        //开始事件的输出路由
                        sequenceFlowList   = ((org.activiti.bpmn.model.StartEvent) f).getOutgoingFlows();
                    }else if(f instanceof org.activiti.bpmn.model.UserTask) {

                        sequenceFlowList   = ((org.activiti.bpmn.model.UserTask) f).getOutgoingFlows();


                        for(SequenceFlow sf :sequenceFlowList)  {

                            String targetRef = sf.getTargetRef();
                            FlowElement ref = process.getFlowElement(targetRef);

                            // nextActivitiIdList.add(ref.getId());

                            list.add(ref);
                        }

                    }else if(f instanceof org.activiti.bpmn.model.SequenceFlow) {


                    }else if(f instanceof org.activiti.bpmn.model.EndEvent) {
                        sequenceFlowList   = ((org.activiti.bpmn.model.EndEvent) f).getOutgoingFlows();
                    }
                    break;
                }

            }

        }
        return list;
    }


    /**
     * @Method 流程流转到下一步
     * @Author MC
根据 assignee 查询出任务,如果存在则设置当前任务的 assignee 为 nextUser
     * @Return 不存在下一个节点返回false;
     * @Date 2019/9/19 0019 18:23
     */
    public boolean completeByAssignee(String assignee,String nextUser) throws Exception {

        HashMap map = new HashMap();

        map.put("nextUser", nextUser);
        Task task = taskService.createTaskQuery().taskAssignee(assignee).singleResult();
        if(task == null){
            System.out.println("下一节点不存在");
            return false;
        }
        taskService.complete(task.getId(),map);
        System.out.println("完成任务 编号为【" + task.getId() + "】,名称为【"+task.getName()+"】的任务");
        return true;
    }

    /**
     * 设置某个节点的审批人员
     * @param taskId
     * @param user
     */
    public void setApproveUser(String taskId,String user) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        task.setAssignee(user);
        taskService.saveTask(task);
    }


    /**
     * 取下一个节点的审批人
     * @param taskId
     * @return
     */
    public List getNextTaskUserByTaskId(String taskId) {
        List list = new ArrayList();
        List fList = getNextNode(taskId);
        for(FlowElement u:fList){
            String str =  ((org.activiti.bpmn.model.UserTask) u).getAssignee();
            list.add(str);
        }
        return list ;
    }


    /**
     * 找当前节点的候选审批人  供流程实例start后调用
     * @param taskId
     * @return
     */
    public List getThisTaskUser(String taskId) {
        List list = new ArrayList();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String taskUser = task.getAssignee();

        //*****************************根据taskUser的配置到自己的表里面去找数据

        list.add(taskUser);
        return list ;
    }

    /**
     * @Method 任务是否完结
     * @Author MC

     * @Return
     * @Date 2019/9/20 0020 11:20
     */
    public boolean isOverTask(String processInstanceId){
        ProcessInstance pi= runtimeService.createProcessInstanceQuery() // 创建流程实例查询
                .processInstanceId(processInstanceId) // 用流程实例id查询
                .singleResult();
        if(pi!=null){
            System.out.println("流程正在执行!");
            return false;
        }else{
            System.out.println("流程已经执行结束!");
        }
        return true;
    }


    /**
     * @Method 历史流程实例查询
     * @Author MC

     * @Return
     * @Date 2019/9/20 0020 11:22
     */
    public  List  queryHisProInstance(String processDefinitionKey){
        List historicProcessInstanceList = processEngine.getHistoryService().createHistoricProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)
                .orderByProcessInstanceEndTime()
                .desc()
                .list();
        /*for(HistoricProcessInstance historicProcessInstance:historicProcessInstanceList){
            System.out.println("历史流程实例id: "+historicProcessInstance.getId());
            System.out.println("历史流程实例的完成时间: "+historicProcessInstance.getEndTime());
        }*/
        return historicProcessInstanceList;
    }


    /**
     * 查询历史流程变量
     */
    public List queryHisProVariable(String processInstanceId){
        List historicVariableInstanceList = processEngine.getHistoryService()
                .createHistoricVariableInstanceQuery()
                .processInstanceId(processInstanceId).list();
        /*for(HistoricVariableInstance historicVariableInstance: historicVariableInstanceList){
            System.out.println("历史流程变量id: "+historicVariableInstance.getId());
            System.out.println("历史流程变量名称: "+historicVariableInstance.getVariableName());
            System.out.println("历史流程变量值: "+historicVariableInstance.getValue());
            System.out.println("==================================================");
        }*/
        return historicVariableInstanceList;
    }


    /**
     * 根据办理人查询历史任务实例
     */
    public List queryHisTaskInstanceByAssignee(String processDefinitionKey,String taskAssignee){
        List historicTaskInstanceList = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
                .processDefinitionKey(processDefinitionKey)
                .taskAssignee(taskAssignee).list();
        /*for(HistoricTaskInstance historicTaskInstance:historicTaskInstanceList){
            System.out.println("历史任务id: "+historicTaskInstance.getId());
            System.out.println("历史任务名称: "+historicTaskInstance.getName());
            System.out.println("历史任务结束时间: "+historicTaskInstance.getEndTime());
            System.out.println("办理人: "+historicTaskInstance.getAssignee());
            System.out.println("==================================================");
        }*/
        return historicTaskInstanceList;
    }



    /**
     * 历史任务查询
     * type: 0:未完成 1:已完成  "":all
     */
    public List historyTaskList(String processInstanceId,String type){
        List list=null;

        if(StringUtils.isEmpty(type)){
            list =  processEngine.getHistoryService() // 历史相关Service
                    .createHistoricTaskInstanceQuery() // 创建历史任务实例查询
                    .processInstanceId(processInstanceId) // 用流程实例id查询
                    .list();
        }else if("0".equals(type)){
            list =  processEngine.getHistoryService() // 历史相关Service
                    .createHistoricTaskInstanceQuery() // 创建历史任务实例查询
                    .processInstanceId(processInstanceId) // 用流程实例id查询
                    .unfinished()
                    .list();
        }else if("1".equals(type)){
            processEngine.getHistoryService() // 历史相关Service
                    .createHistoricTaskInstanceQuery() // 创建历史任务实例查询
                    .processInstanceId(processInstanceId) // 用流程实例id查询
                    .finished() // 查询已经完成的任务
                    .list();
        }
       /* for(HistoricTaskInstance hti:list){
            System.out.println("任务ID:"+hti.getId());
            System.out.println("流程实例ID:"+hti.getProcessInstanceId());
            System.out.println("任务名称:"+hti.getName());
            System.out.println("办理人:"+hti.getAssignee());
            System.out.println("开始时间:"+hti.getStartTime());
            System.out.println("结束时间:"+hti.getEndTime());
            System.out.println("=================================");
        }*/

       return list;
    }

    /**
     * 已完成的历史活动查询
     */
    public List historyActInstanceList(String processInstanceId){
        List  list=processEngine.getHistoryService() // 历史相关Service
                .createHistoricActivityInstanceQuery() // 创建历史活动实例查询
                .processInstanceId(processInstanceId) // 执行流程实例id
                .finished()
                .list();
       /* for(HistoricActivityInstance hai:list){
            System.out.println("活动ID:"+hai.getId());
            System.out.println("流程实例ID:"+hai.getProcessInstanceId());
            System.out.println("活动名称:"+hai.getActivityName());
            System.out.println("办理人:"+hai.getAssignee());
            System.out.println("开始时间:"+hai.getStartTime());
            System.out.println("结束时间:"+hai.getEndTime());
            System.out.println("=================================");
        }*/
       return list;
    }

} 

 

act全局变量所需的实体对象leave:

 

package com.example.demo.model;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * @ProjectName: demo
 * @Package: com.example.demo.service.model
 * @ClassName: Leave
 * @Author: MC
 * @Description: ${description}
 * @Date: 2019/9/19 0019 13:14
 * @Version: 1.0
 */
@Data
public class Leave implements Serializable {
    private static final long serialVersionUID = 2248469053125414262L;

    private String userId;

    private Boolean submit;

    private Date startDate;

    private Date endDate;

    private float totalDay;

    private String desc;

    private String taskId;

    private String taskName;

    private String approver1;

    private Boolean agree1;

    private String approveDesc1;

    private String approver2;

    private Boolean agree2;

    private String approveDesc2;

    private Boolean agree3;

    private String approveDesc3;
}

 具体操作的代码:

package com.example.demo.web;

import com.example.demo.model.Leave;
import com.example.demo.utils.ActivitiUtil;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: demo
 * @Package: com.example.demo.web
 * @ClassName: BingxingController
 * @Author: MC
 * @Description: ${description}
 * @Date: 2019/9/23 0023 14:41
 * @Version: 1.0
 */
@RestController
@RequestMapping("/bingxing")
public class BingxingController {
    @Autowired
    private ActivitiUtil activitiUtil;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService ;

    //----------------------------
    // 注意:bingxing.bpmn没有设置userTask标签的 activiti:assignee 属性,所以获取task需要根据ID获取
    // 另外,连接线的限制条件获取的是全局变量的bingxing,我之前写错了,写成获取全局变量的leave了
    // -----------------------------

    @RequestMapping(value = "/start")
    public String start (){
        activitiUtil.deploy("processes/bingxing.bpmn");
        Map map = new HashMap<>();//流程变量对象
        Leave leave = new Leave();
        leave.setUserId("shenqing");
        map.put("bingxing",leave);//其所存act_ru_variable表name属性值对应其map的Key
        Map startMap = activitiUtil.start(map, "bingxingleveal");
        String processInstanceId = startMap.get("processInstanceId").toString();

        return processInstanceId;
    }

    @RequestMapping(value = "/approve")
    public void approve(@RequestParam  String processInstanceId){
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskDefinitionKey("shenqing")//注意:这里是因为xml文件中的userTask标签没有设置activiti:assignee属性时获取的方法
                .singleResult();

        String taskId = task.getId();
        activitiUtil.setApproveUser(taskId, "shenqing");
//        Task task = activitiUtil.queryTask("shenqing",processInstanceId);
        Map map = new HashMap<>();
        // 获取流程参数  对应启动流程时,入参的参数leave
        Leave variable = (Leave)taskService.getVariable(taskId, "bingxing");
        // 从入参的表单对象中取值,设置流程参数对象的值
        variable.setSubmit(true);
        map.put("bingxing",variable);
        taskService.complete(taskId,map);

    }

    @RequestMapping(value = "/approve2")
    public void approve2(@RequestParam  String processInstanceId){
       /* Task shenpiBtask = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskDefinitionKey("shenpiB")//注意:这里是因为xml文件中的userTask标签没有设置activiti:assignee属性时获取的方法
                .singleResult();

        String shenpiBtaskId = shenpiBtask.getId();
        taskService.complete(shenpiBtaskId);*/

        Task shenpiAtask = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskDefinitionKey("shenpiA")//注意:这里是因为xml文件中的userTask标签没有设置activiti:assignee属性时获取的方法
                .singleResult();

        String shenpiAtaskId = shenpiAtask.getId();
//        Task task = activitiUtil.queryTask("shenqing",processInstanceId);
        Map map = new HashMap<>();
        // 获取流程参数  对应启动流程时,入参的参数leave
        Leave variable = (Leave)taskService.getVariable(shenpiAtaskId, "bingxing");
        // 从入参的表单对象中取值,设置流程参数对象的值
        variable.setAgree1(true);
//        map.put("bingxing",variable);
        map.put("leave",variable);//原来画图画错了,连接线的条件设置成了leave了。。。。。。
        taskService.complete(shenpiAtaskId,map);

    }

    @RequestMapping(value = "/approve3")
    public void approve3(@RequestParam  String processInstanceId){
        Task shenpiAtask = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskDefinitionKey("shenpiC")//注意:这里是因为xml文件中的userTask标签没有设置activiti:assignee属性时获取的方法
                .singleResult();

        String shenpiAtaskId = shenpiAtask.getId();
//        Task task = activitiUtil.queryTask("shenqing",processInstanceId);
        Map map = new HashMap<>();
        // 获取流程参数  对应启动流程时,入参的参数leave
        Leave variable = (Leave)taskService.getVariable(shenpiAtaskId, "leave");
        // 从入参的表单对象中取值,设置流程参数对象的值
        variable.setAgree3(true);
//        map.put("bingxing",variable);
        map.put("leave",variable);//原来画图画错了,连接线的条件设置成了leave了。。。。。。
        taskService.complete(shenpiAtaskId,map);

    }

    @RequestMapping(value = "/approve4")
    public void approve4(@RequestParam  String processInstanceId){
        Task shenpiAtask = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)//使用流程实例ID
                .taskDefinitionKey("_10")//注意:这里是因为xml文件中的userTask标签没有设置activiti:assignee属性时获取的方法
                .singleResult();

        String shenpiAtaskId = shenpiAtask.getId();
        taskService.complete(shenpiAtaskId);
    }

}

 

如果你看过上一篇博客排他网关,你会发现,排他网关的xml中userTask标签体设置了activiti:assignee而并行的xml中没有设置,在启动流程后,可以观察act_ru_task表中的assignee字段值为空,但是def_key字段值对应xml中userTask标签体的ID属性。

仔细看下approve2方法,我注释了一块代码,这一块可以单独写一个方法进行观察ru_task表数据,shenpiB和shenpiA会在task表中出现两条任务数据。

具体按照代码走一遍,最好自己上手敲,才会慢慢理解。

你可能感兴趣的:(activiti)