zoukankan      html  css  js  c++  java
  • flowable的多人会签和一票否决

    项目结构:

    接下来代码:
    
    Duorenhuiqian.bpmn20.xml:
    
    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
      <process id="countersign" name="Duorenhuiqian" isExecutable="true">
        <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
        <userTask id="UserTask1" name="U1" flowable:assignee="${assignee}" flowable:formFieldValidation="true">
          <extensionElements>
            <!--<flowable:executionListener event="start" class="com.cars.ngtdms.cooperation.flowable.listener.CountersignListener"></flowable:executionListener>-->
            <flowable:executionListener event="start" delegateExpression="${countersignListener}"></flowable:executionListener>
            <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
          </extensionElements>
          <multiInstanceLoopCharacteristics isSequential="false" flowable:collection="assigneeList" flowable:elementVariable="assignee">
            <completionCondition>${multiInstance.accessCondition(execution)}</completionCondition>
          </multiInstanceLoopCharacteristics>
        </userTask>
        <sequenceFlow id="sid-50622098-77B0-4413-A1D4-088B47DEC95F" sourceRef="startEvent1" targetRef="UserTask1"></sequenceFlow>
        <userTask id="UserTask2" name="U2" flowable:assignee="WXF" flowable:formFieldValidation="true">
          <extensionElements>
            <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
          </extensionElements>
        </userTask>
        <endEvent id="sid-814B8939-308D-4003-8B35-B750DC8F8A5C"></endEvent>
        <exclusiveGateway id="getWay" name="getWay"></exclusiveGateway>
        <userTask id="UserTask3" name="U3" flowable:assignee="PXY" flowable:formFieldValidation="true">
          <extensionElements>
            <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
          </extensionElements>
        </userTask>
        <endEvent id="sid-4C2BFAF2-08AC-4F89-A964-046EA583F0B5"></endEvent>
        <sequenceFlow id="sid-CE25CF8A-5BF2-4227-A747-98F6A053283E" sourceRef="UserTask3" targetRef="sid-4C2BFAF2-08AC-4F89-A964-046EA583F0B5"></sequenceFlow>
        <sequenceFlow id="sid-0F397F15-5685-4DF0-B7E0-75C3AB43F6D8" sourceRef="UserTask2" targetRef="sid-814B8939-308D-4003-8B35-B750DC8F8A5C"></sequenceFlow>
        <sequenceFlow id="sid-74E664CC-0FC9-49A6-A47C-BCFA1198F074" sourceRef="UserTask1" targetRef="getWay"></sequenceFlow>
        <sequenceFlow id="repply" name="通过" sourceRef="getWay" targetRef="UserTask2">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="reject" name="否决" sourceRef="getWay" targetRef="UserTask3">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='否决'}]]></conditionExpression>
        </sequenceFlow>
      </process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_countersign">
        <bpmndi:BPMNPlane bpmnElement="countersign" id="BPMNPlane_countersign">
          <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
            <omgdc:Bounds height="30.0" width="30.0" x="135.0" y="290.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="UserTask1" id="BPMNShape_UserTask1">
            <omgdc:Bounds height="80.0" width="100.0" x="255.0" y="265.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="UserTask2" id="BPMNShape_UserTask2">
            <omgdc:Bounds height="80.0" width="100.0" x="495.0" y="120.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="sid-814B8939-308D-4003-8B35-B750DC8F8A5C" id="BPMNShape_sid-814B8939-308D-4003-8B35-B750DC8F8A5C">
            <omgdc:Bounds height="28.0" width="28.0" x="750.0" y="146.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="getWay" id="BPMNShape_getWay">
            <omgdc:Bounds height="40.0" width="40.0" x="525.0" y="285.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="UserTask3" id="BPMNShape_UserTask3">
            <omgdc:Bounds height="80.0" width="100.0" x="495.0" y="405.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="sid-4C2BFAF2-08AC-4F89-A964-046EA583F0B5" id="BPMNShape_sid-4C2BFAF2-08AC-4F89-A964-046EA583F0B5">
            <omgdc:Bounds height="28.0" width="28.0" x="645.0" y="431.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNEdge bpmnElement="sid-50622098-77B0-4413-A1D4-088B47DEC95F" id="BPMNEdge_sid-50622098-77B0-4413-A1D4-088B47DEC95F">
            <omgdi:waypoint x="164.94999923927443" y="305.0"></omgdi:waypoint>
            <omgdi:waypoint x="255.0" y="305.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sid-74E664CC-0FC9-49A6-A47C-BCFA1198F074" id="BPMNEdge_sid-74E664CC-0FC9-49A6-A47C-BCFA1198F074">
            <omgdi:waypoint x="354.9499999999567" y="305.10384615384606"></omgdi:waypoint>
            <omgdi:waypoint x="525.4583333333242" y="305.4583333333333"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="reject" id="BPMNEdge_reject">
            <omgdi:waypoint x="545.431654676259" y="324.51130481667866"></omgdi:waypoint>
            <omgdi:waypoint x="545.1431899641577" y="405.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sid-0F397F15-5685-4DF0-B7E0-75C3AB43F6D8" id="BPMNEdge_sid-0F397F15-5685-4DF0-B7E0-75C3AB43F6D8">
            <omgdi:waypoint x="594.9499999999925" y="160.0"></omgdi:waypoint>
            <omgdi:waypoint x="750.0" y="160.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="repply" id="BPMNEdge_repply">
            <omgdi:waypoint x="545.4310344827586" y="285.4310344827586"></omgdi:waypoint>
            <omgdi:waypoint x="545.1372852233677" y="199.95"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="sid-CE25CF8A-5BF2-4227-A747-98F6A053283E" id="BPMNEdge_sid-CE25CF8A-5BF2-4227-A747-98F6A053283E">
            <omgdi:waypoint x="594.9499999997366" y="445.0"></omgdi:waypoint>
            <omgdi:waypoint x="645.0" y="445.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </definitions>
    application.yml:
    
    spring:
      datasource:
        url: jdbc:mysql://127.0.0.1:3306/foujueflowable?characterEncoding=UTF-8
        password: root
        username: root
        driver-class-name: com.mysql.jdbc.Driver
    flowable:
      #关闭定时任务job
      async-executor-activate: false
    scale: 0.5
     
    assignee: person1,person2,person3,person4
     
    yipiaofoujueren: pxy
    ExpenseController:
    package com.cars.ngtdms.cooperation.controller;
     
    import org.flowable.engine.ProcessEngine;
    import org.flowable.engine.RepositoryService;
    import org.flowable.engine.RuntimeService;
    import org.flowable.engine.TaskService;
    import org.flowable.engine.delegate.DelegateExecution;
    import org.flowable.engine.runtime.ProcessInstance;
    import org.flowable.task.api.Task;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
     
    import java.util.*;
     
    @Controller
     
    @RequestMapping(value = "expense")
    @ResponseBody
    public class ExpenseController {
        @Autowired
        private RuntimeService runtimeService;
        @Autowired
        private TaskService taskService;
        @Autowired
        private RepositoryService repositoryService;
        @Autowired
        private ProcessEngine processEngine;
     
        @Value("#{'${yipiaofoujueren}'.split(',')}")
        private List yipiaofoujueren;
     
     
        /**
         * 开启
         * @return
         */
        @RequestMapping(value = "add")
        public String StartTask(){
            runtimeService.startProcessInstanceByKey("countersign");
            return "OK";
        }
     
     
     
        /**
         * 执行
         * @return
         */
        @RequestMapping(value = "do")
        public List<String> DoTask(String name){
           // List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(name).list();
            List<Task> tasks = taskService.createTaskQuery().taskAssignee(name).list();
            List<String> list = new ArrayList<>();
            System.out.println("[");
            for (Task task:tasks
                 ) {
     
                System.out.println(task.getId());
                list.add("id:"+task.getId()+"   name:"+task.getName()+"    Assignee:"+task.getAssignee());
     
            }
            System.out.println("]");
            return list;
        }
     
     
        /**
         * 完成
         * @return
         */
        @RequestMapping(value = "done")
        @Transactional
        public String DoneTask(String name,String taskId,String flg){
            List<Task> list = taskService.createTaskQuery().taskAssignee(name).list();
            List<String> taskList= new ArrayList<>();
            String taskId1="";
            for (Task task : list) {
                taskList.add("id:"+task.getId()+"name"+task.getName()+"审批人:"+task.getAssignee());
                taskId1 = task.getId();
                System.out.println(taskId);
            }
            System.out.println("完成前"+taskList);
           if ("n".equals(flg)){
                if (yipiaofoujueren.contains(name)){
                    Map<String,Object> map = new HashMap<>();
                    Integer reject = (int)taskService.getVariable(taskId1,"reject");
                    map.put("reject",reject+1);
                    taskService.complete(taskId,map);
                }else {
                    Map<String,Object> map = new HashMap<>();
                    Integer rejectPeson = (int)taskService.getVariable(taskId1,"rejectPeson");
                    map.put("rejectPeson",rejectPeson+1);
                    taskService.complete(taskId,map);
     
                }
            } else if ("y".equals(flg)){
               Map<String,Object> map = new HashMap<>();
               Integer agreePeson = (int)taskService.getVariable(taskId1,"agreePeson");
               map.put("agreePeson",agreePeson+1);
               taskService.complete(taskId,map);
           }
     
            List<Task> list1 = taskService.createTaskQuery().taskAssignee(name).list();
            List<String> taskList1= new ArrayList<>();
            for (Task task : list1) {
                taskList1.add("id:"+task.getId()+"name"+task.getName()+"审批人:"+task.getAssignee());
            }
            System.out.println("完成后"+taskList1);
            return "通过";
        }
     
     
        /**
         * 查看当前任务名
         * @return
         */
        @RequestMapping(value = "select")
        public List<String> SelectTask(){
            List<Task> list = taskService.createTaskQuery().list();
            List<String> taskList=new ArrayList<>();
            for (Task task : list) {
                taskList.add(task.getId()+"-----------"+task.getName());
     
            }
     
            return taskList;
        }
     
     
     
    }
    CountersignListener:
    package com.cars.ngtdms.cooperation.flowable.listener;
     
    import org.flowable.engine.delegate.DelegateExecution;
    import org.flowable.engine.delegate.ExecutionListener;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
     
     
    import java.util.HashMap;
    import java.util.List;
    @Component
    public class CountersignListener implements ExecutionListener {
        @Value("#{'${assignee}'.split(',')}")
        private List list;
        @Override
        public void notify(DelegateExecution delegateExecution) {
            System.out.println("读取的审批人是:"+list);
                HashMap<String, Object> map = new HashMap<>();
                //定义的人员列表4人
                //String[] person = { "person1", "person2", "person3","pxy" };
                //map.put("assigneeList", Arrays.asList(person));
                map.put("assigneeList", list);
                map.put("reject", 0);
                map.put("rejectPeson", 0);
                map.put("agreePeson", 0);
                delegateExecution.setVariables(map);
     
        }
    }
    ApplicationPxy:
    package com.cars.ngtdms.cooperation;
     
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
     
     
    @SpringBootApplication
    //@EnableDiscoveryClient
    public class ApplicationPxy {
     
        public static void main(String[] args) {
            SpringApplication.run(ApplicationPxy.class,args);
        }
    }
    MultiInstanceCompleteTask:
    package com.cars.ngtdms.cooperation;
     
    import org.flowable.engine.delegate.DelegateExecution;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
     
    import java.io.Serializable;
     
    @Component(value = "multiInstance")
    public class MultiInstanceCompleteTask implements Serializable{
        /**
         * 评估结果判定条件
         * @param execution 分配执行实例
         */
        @Value("${scale}")
        private String scaleStr;
     
     
        public boolean accessCondition(DelegateExecution execution) {
            Double scale = Double.valueOf(scaleStr);
            System.out.println("比例是:"+scale);
            System.out.println("I am running!!!!!!");
            System.out.println("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT");
            //已完成的实例数
            int completedInstance = (int) execution.getVariable("nrOfCompletedInstances");
            System.out.println("此时已完成的实例数为:"+completedInstance);
            //否决判断,一票否决
            if (execution.getVariable("reject") != null) {
                int rejectCount = (int) execution.getVariable("reject");
                System.out.println("reject:"+rejectCount);
                if (rejectCount > 0) {
                    //输出方向为拒绝
                    execution.setVariable("outcome", "否决");
                    //一票否决其他实例没必要做,结束
                    return true;
                }
            }
            //获取所有的实例数
            int AllInstance = (int)execution.getVariable("nrOfInstances");
            System.out.println("总实例数目:"+AllInstance);
            //获取不同意的次数
            int rejectPeson = (int)execution.getVariable("rejectPeson");
            System.out.println("不同意的人的个数为:"+rejectPeson);
            //获取同意人的次数
            int agreePeson = (int)execution.getVariable("agreePeson");
            System.out.println("同意的人的个数为:"+agreePeson);
     
     
            //所有实例任务未全部做完则继续其他实例任务
            if (completedInstance != AllInstance) {
                //加入不同意的人数大于设置比例*总人数
                if (rejectPeson*1.00/AllInstance>(1-scale)){
                    execution.setVariable("outcome", "否决");
                    return true;
                }
                if (agreePeson*1.00/AllInstance>=scale){
                    execution.setVariable("outcome", "通过");
                    return true;
                }
     
                return false;
            } else {
                //输出方向为赞同
                execution.setVariable("outcome", "通过");
                //所有都做完了没被否决,结束
                return true;
            }
     
     
     
        }
    }
    依赖:
    
     <!--flowable工作流依赖-->
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-spring-boot-starter</artifactId>
                <version>6.4.1</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>

    好了 这样就可以直接运行了,数据库的名字要设置对

    然后开始解释:

    多人会签意思是这一个任务需要很多人来进行审批,同意总数超过或者未超过多少比例的时候会执行对应的某个任务。

    还有个就是一票否决,指定某个人,它反对就直接相当于全部反对

    代码解释:

    首先配置文件application:

    然后xml文件:

    标签的具体工作原理这里不再赘述,可以自行百度

    然后就是监听器CountersignListener:

    然后就是执行器的配置内容了MultiInstanceCompleteTask:

    有点长久分开截屏写了

    箭头指向的地方就是一票否决,在监听器里边对reject进行了初始化,这里通过获取reject来判断它的值如果大于零就直接否决,

    我这里为了能体现否决和同意,我一共设置了三个任务,第一个任务是会签,第二个任务和第三个任务一个是同意一个是否决对应的任务,他们是通过路由进行相关联的,路由判断outcome是"否决"还是"通过"然后路由到第二个任务或者第三个任务

    他这个方法呢 如果是返回的true,那么就直接结束第一个会签任务,如果返回的是false那么会继续执行第一个会签任务

    接下来继续:

    这里有个小BUG  如果一票否决的人还没有执行,那么但凡执行了上边的那个通过,那这个任务就直接跳过去了,他就不能一票否决了,其实这里可以进行判断,如果这里一票否决的人没有执行就让它返回false。

    然后继续来看ExpenseController类:

    好的 接下来第一个方法,根据审批人的ID来获取任务的ID:

    第二个方法,根据审批人的名字、任务的id、flg来进行执行任务

    这里要注意了!!!!这里是flg不是flag

    审批人的名字就不用说了,任务id就是第一个方法获取的任务的id,flg呢就是来判断是否同意的,n代表不同意,y代表同意

    这里比较简单,代码上也有注释,就解释一下逻辑处理这一点好了:

    很好,然后第三个方法!:

    它就是来查看当前xml就是这个flowable的当前任务,专业术语我忘记怎么说了,emmm  当前实例?不行 不行 忘记了

    执行它可以到执行到哪个任务了

    好了 没了 就这样了 emmmm  这里写的是审批人是相当于直接塞进去的,也可以手动的塞进去,就是add的那个方法,在进行加载xml的时候,创建一个map,然后序列化一下,放到那个方法的第二个参数的位置就行了。

  • 相关阅读:
    canvas gamebricks
    javascript 判断对象的值是否相等
    让控件全屏显示(WinForm)
    网络视频监控
    回调函数
    [导入][链接]FreeBSD + Sun Java
    [导入][一点一滴学英语]20060330
    [导入][来自网络] 酸酸甜甜就是我 不用我多介绍了 可是你是否听过天津话的版本?
    [导入][链接]差点漏掉 Eclipse 3.2 M6出来了
    [导入][链接]Five reasons why you should never use PostgreSQL
  • 原文地址:https://www.cnblogs.com/xianz666/p/13563124.html
Copyright © 2011-2022 走看看