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

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

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

 

接下来准备绘制流程图:

具体的xml代码如下:

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/testm1539766523202" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1539766523202" name=""
             targetNamespace="http://www.activiti.org/testm1539766523202" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="bingxingleveal" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="_2" name="StartEvent"/>
    <userTask activiti:exclusive="true" id="shenqing" name="提交申请"/>
    <parallelGateway gatewayDirection="Unspecified" id="_4" name="ParallelGateway"/>
    <userTask activiti:exclusive="true" id="shenpiA" name="审批A"/>
    <userTask activiti:exclusive="true" id="shenpiB" name="审批B"/>
    <userTask activiti:exclusive="true" id="shenpiC" name="审批C"/>
    <exclusiveGateway gatewayDirection="Unspecified" id="_8" name="ExclusiveGateway"/>
    <parallelGateway gatewayDirection="Unspecified" id="_9" name="ParallelGateway"/>
    <userTask activiti:exclusive="true" id="_10" name="最终审批"/>
    <endEvent id="_11" name="EndEvent"/>
    <sequenceFlow id="_12" sourceRef="_2" targetRef="shenqing"/>
    <sequenceFlow id="_13" sourceRef="shenqing" targetRef="_4"/>
    <sequenceFlow id="_14" sourceRef="_4" targetRef="shenpiB">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${bingxing.submit==true}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_15" sourceRef="_4" targetRef="shenpiA">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${bingxing.submit==true}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_16" sourceRef="shenpiB" targetRef="_9"/>
    <sequenceFlow id="_18" sourceRef="shenpiC" targetRef="_8"/>
    <sequenceFlow id="_19" name="驳回" sourceRef="_8" targetRef="shenpiA">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${bingxing.agree3==false}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_20" name="同意" sourceRef="_8" targetRef="_9">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${bingxing.agree3==true}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_21" sourceRef="_9" targetRef="_10"/>
    <sequenceFlow id="_22" sourceRef="_10" targetRef="_11"/>
    <sequenceFlow id="_3" sourceRef="shenpiA" targetRef="shenpiC">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${bingxing.agree1==true}]]></conditionExpression>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    <bpmndi:BPMNPlane bpmnElement="bingxingleveal">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <dc:Bounds height="32.0" width="32.0" x="10.0" y="190.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="shenqing" id="Shape-shenqing">
        <dc:Bounds height="55.0" width="85.0" x="125.0" y="180.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
        <dc:Bounds height="32.0" width="32.0" x="275.0" y="190.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="shenpiA" id="Shape-shenpiA">
        <dc:Bounds height="55.0" width="85.0" x="400.0" y="80.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="shenpiB" id="Shape-shenpiB">
        <dc:Bounds height="55.0" width="85.0" x="385.0" y="310.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="shenpiC" id="Shape-shenpiC">
        <dc:Bounds height="55.0" width="85.0" x="550.0" y="85.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_8" id="Shape-_8" isMarkerVisible="false">
        <dc:Bounds height="32.0" width="32.0" x="735.0" y="110.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_9" id="Shape-_9">
        <dc:Bounds height="32.0" width="32.0" x="745.0" y="205.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_10" id="Shape-_10">
        <dc:Bounds height="55.0" width="85.0" x="900.0" y="210.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_11" id="Shape-_11">
        <dc:Bounds height="32.0" width="32.0" x="1105.0" y="230.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="shenqing" targetElement="_4">
        <di:waypoint x="210.0" y="207.5"/>
        <di:waypoint x="275.0" y="206.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_2" targetElement="shenqing">
        <di:waypoint x="42.0" y="206.0"/>
        <di:waypoint x="125.0" y="207.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_15" id="BPMNEdge__15" sourceElement="_4" targetElement="_5">
        <di:waypoint x="290.0" y="191.0"/>
        <di:waypoint x="290.0" y="110.0"/>
        <di:waypoint x="400.0" y="110.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_14" id="BPMNEdge__14" sourceElement="_4" targetElement="_6">
        <di:waypoint x="290.0" y="221.0"/>
        <di:waypoint x="290.0" y="305.0"/>
        <di:waypoint x="385.0" y="337.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_16" id="BPMNEdge__16" sourceElement="_6" targetElement="_9">
        <di:waypoint x="470.0" y="335.0"/>
        <di:waypoint x="760.0" y="335.0"/>
        <di:waypoint x="760.0" y="236.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_19" id="BPMNEdge__19" sourceElement="_8" targetElement="_5">
        <di:waypoint x="751.0" y="110.0"/>
        <di:waypoint x="630.0" y="40.0"/>
        <di:waypoint x="442.5" y="80.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_18" id="BPMNEdge__18" sourceElement="_7" targetElement="_8">
        <di:waypoint x="635.0" y="112.5"/>
        <di:waypoint x="735.0" y="126.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_3" id="BPMNEdge__3" sourceElement="_5" targetElement="_7">
        <di:waypoint x="500.0" y="107.5"/>
        <di:waypoint x="550.0" y="112.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_20" id="BPMNEdge__20" sourceElement="_8" targetElement="_9">
        <di:waypoint x="756.0" y="137.0"/>
        <di:waypoint x="756.0" y="210.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_22" id="BPMNEdge__22" sourceElement="_10" targetElement="_11">
        <di:waypoint x="985.0" y="237.5"/>
        <di:waypoint x="1105.0" y="246.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_21" id="BPMNEdge__21" sourceElement="_9" targetElement="_10">
        <di:waypoint x="777.0" y="221.0"/>
        <di:waypoint x="900.0" y="237.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

 该实例图中有排他网关和并行网关,避免理解错误。菱形中间带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<String,Object> start(Map<String,Object> 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<String, Object> 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<ProcessInstance> 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<FlowElement> 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<FlowElement> getNextNode(String taskId) {

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

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

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

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

        List<Process> processList = bpmnModel.getProcesses();

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

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


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

                    List<SequenceFlow>  sequenceFlowList = new ArrayList<SequenceFlow>();
                    //通过反射来判断是哪种类型
                    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<String,Object> map = new HashMap<String,Object>();

        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<String> getNextTaskUserByTaskId(String taskId) {
        List<String> list = new ArrayList<String>();
        List<FlowElement> 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<String> getThisTaskUser(String taskId) {
        List<String> list = new ArrayList<String>();
        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<HistoricProcessInstance>  queryHisProInstance(String processDefinitionKey){
        List<HistoricProcessInstance> 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<HistoricVariableInstance> queryHisProVariable(String processInstanceId){
        List<HistoricVariableInstance> 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<HistoricTaskInstance> queryHisTaskInstanceByAssignee(String processDefinitionKey,String taskAssignee){
        List<HistoricTaskInstance> 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<HistoricTaskInstance> historyTaskList(String processInstanceId,String type){
        List<HistoricTaskInstance> 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<HistoricActivityInstance> historyActInstanceList(String processInstanceId){
        List<HistoricActivityInstance>  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<String,Object> map = new HashMap<>();//流程变量对象
        Leave leave = new Leave();
        leave.setUserId("shenqing");
        map.put("bingxing",leave);//其所存act_ru_variable表name属性值对应其map的Key
        Map<String, Object> 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<String,Object> 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<String,Object> 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<String,Object> 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表中出现两条任务数据。

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不能吃辣的JAVA程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值