深入探究Camunda加签问题

简介: camunda加签的两种方式

前言

这里我们先抛出两个大问题,整篇文章针对这两个大问题再详细解析。

首先我们在设计流程定义时,流程节点可能是或签也可能是会签

会签:指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批,需全部同意之后,审批才可到下一审批节点。
或签:指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批,只要其中任意一人审批即可到下一审批节点。  

当前会签也可以是比例签,比如节点上的审批人同意的超过60%就算通过。此时我们需要考虑的问题如下:

问题一:被加签人如何加到节点上

问题二:加签后是否会影响节点的通过【不同通过规则的节点】

如何加签

这里还需要区分设置审批人的方式:

  1. 在发起流程实例时,一次性将所有节点的审批人全部设置完成
  2. 通过监听器来设置审批人

在设计流程定义时,节点上主要设置这几个参数

1是分配到待办任务的人,变量名和3保持一致;2是我们要传入的参数名,3是用来遍历2中集合的变量名,4是节点通过的条件。

关于怎么发布流程定义可以查看我之前的文章,不赘述了。

一次性设置审批人

@GetMapping("/startProcessInstance")
publicStringstartProcessInstance(@RequestParam("processDefineKey")StringprocessDefineKey,
@RequestParam("businessKey")StringbusinessKey) {
Map<String, Object>map=newHashMap<>();
List<String>userOneList=newArrayList<>();
userOneList.add("zhangsan");
userOneList.add("lisi");
List<String>userTwoList=newArrayList<>();
userTwoList.add("wangwu");
userTwoList.add("maliu");
map.put("initiator","lonewalker");
map.put("userOneList", userOneList);
map.put("userTwoList", userTwoList);
ProcessInstanceprocessInstance=runtimeService.startProcessInstanceByKey(processDefineKey, businessKey, map);
//默认把发起人节点审批通过Tasktask=taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
StringtaskId=task.getId();
taskService.complete(taskId);
returnprocessInstance.getProcessInstanceId();
    }


来看一下流程图,生成两个用户任务


我们开始加签,这里流程跑到第二个节点时会创建和userOneList.size 的Task,想在这个节点加签,就得想办法让这个事件再触发一次。

@GetMapping("/addSign")
publicvoidaddSign(@RequestParam("processInstanceId")StringprocessInstanceId,
@RequestParam("nodeId")StringnodeId,
@RequestParam("userId")StringuserId){
runtimeService.createProcessInstanceModification(processInstanceId)
                .startBeforeActivity(nodeId)
                .setVariable("userOne",userId)
                .setAnnotation("加签")
                .execute();
    }

请求接口后查看已经成功加签

按节点动态设置审批人

此时我们需要通过执行监听器来完成审批人的设置,两种监听器的区别可查看此篇

修改流程定义,在或签节点之前的连线上设置执行监听器。


自定义一个执行监听器

@ComponentpublicclassCustomExecutionListenerimplementsExecutionListener {
@Overridepublicvoidnotify(DelegateExecutionexecution) throwsException {
System.out.println("触发了执行监听器");
List<String>userOneList=newArrayList<>();
userOneList.add("zhangsan");
userOneList.add("lisi");
execution.setVariable("userOneList",userOneList);
    }
}

发起流程实例的接口中把或签节点审批人去掉


然后部署,发起流程实例


此时我们加签的逻辑和之前一样,但是实现不一样了:

@GetMapping("/addSign")
publicvoidaddSign(@RequestParam("processInstanceId")StringprocessInstanceId,
@RequestParam("nodeId")StringnodeId){
//获取实例的流程定义 这里主要是为了拿到节点前的那条线的IdProcessInstanceprocessInstance=runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
BpmnModelInstancebpmnModel=repositoryService.getBpmnModelInstance(processInstance.getProcessDefinitionId());
ModelElementInstancemodelElement=bpmnModel.getModelElementById(nodeId);
UserTaskuserTask= (UserTask) modelElement;
Collection<SequenceFlow>incoming=userTask.getIncoming();
StringtransitionId="";
if (incoming.stream().findFirst().isPresent()) {
transitionId=incoming.stream().findFirst().get().getId();
        } else {
thrownewProcessException(ErrorCodeEnum.PROC_TASK_REJECT_FAILURE);
        }
runtimeService.createProcessInstanceModification(processInstanceId)
                .setAnnotation("加签")
                .startTransition(transitionId)
                .execute();
    }

重新触发或签节点前连线上的执行监听器,然后加了一个sunjiu


调用加签接口后:


问题:
此时我模拟sunjiu审批,因为是或签节点按正常情况,流程会到会签节点,或签节点结束。


刚刚加签的那个人确实审批通过了,也到会签节点了,但是原先的两个人还停留在或签,看一下原因
因为重新解析了userOneList,导致加签的任务和原来的任务它们的父环节实例不一致


这是不是意味着,这两个人的其中一人审批都会再次触发会签节点前连线上的执行监听器。这明显不是我们想要的。改一下审批接口

@GetMapping("/agreeTask")
publicvoidagreeTask(@RequestParam("taskId")StringtaskId){
Tasktask=taskService.createTaskQuery().taskId(taskId).singleResult();
StringprocessInstanceId=task.getProcessInstanceId();
//完成任务taskService.complete(taskId);
List<Task>activeTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).active().list();
if (CollUtil.isNotEmpty(activeTaskList)){
//如果nodeIdSet大于1 就说明下一节点开启待办任务了,而当前节点还有待办任务  说明刚刚处理的这个任务是或签操作Set<String>nodeIdSet=activeTaskList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toSet());
if (nodeIdSet.size() >1){
//查询当前节点未完成的实例List<HistoricActivityInstance>unfinishedInstanceList=historyService.createHistoricActivityInstanceQuery().
processInstanceId(processInstanceId).activityId(task.getTaskDefinitionKey()).unfinished().list();
if (CollUtil.isNotEmpty(unfinishedInstanceList)){
//说明或签节点有加签for (HistoricActivityInstanceinstance : unfinishedInstanceList) {
runtimeService.createProcessInstanceModification(processInstanceId).cancelActivityInstance(instance.getId()).execute();
                    }
                }
            }
        }
    }

重新发起一条流程实例,将上述操作再走一遍:

注意:这种情况下可以一次性加多个人,但是会签就不行了,因为这种方式加签会产生多个multiInstanceBody 。 比如会签节点现在有两个审批人a、b,那它们俩的multiInstanceBody 是同一个,但是如果我用上述加签方式加签 c 后会又产生一个multiInstanceBody,当c审批通过时会触发下一节点连线上的执行监听器,a、b审批通过后又会触发一次

此时就要利用好这个Assignee变量

@GetMapping("/addSign")
publicvoidaddSign(@RequestParam("processInstanceId")StringprocessInstanceId,
@RequestParam("nodeId")StringnodeId,
@RequestParam("userId")StringuserId){
runtimeService.createProcessInstanceModification(processInstanceId)
                  .startBeforeActivity(nodeId)
                  .setVariable("userTwo",userId)
                  .execute();
    }

个人觉得最好的方式还是这种,而上述的也是为了提供给大家更好的思路,毕竟需求都是不一样的

扩展

有朋友会疑问为什么不用这个参数,这个相当于事先知道这个节点上有几个审批人,比如我设置5,那到这个节点就会创建5个待办任务,那如果是角色呢?所以才用上述的监听器去查询角色对应的人数,从而实现动态设置审批人



相关文章
|
6月前
|
JSON 关系型数据库 测试技术
Eolink神技之五、API自动化——定时任务
Eolink神技之五、API自动化——定时任务
88 0
|
6月前
|
前端开发
基于jeecg-boot的flowable流程自定义业务驳回到发起人的一种处理方式
基于jeecg-boot的flowable流程自定义业务驳回到发起人的一种处理方式
296 0
|
3月前
|
前端开发 Java API
一文教会你如何简单使用Fegin进行远程服务调用
这篇文章介绍了如何在分布式微服务架构中使用Feign进行远程服务调用,包括Feign的基本介绍、使用步骤,以及在项目中的实际运用方法,并通过测试验证了调用远程服务的成功性。
一文教会你如何简单使用Fegin进行远程服务调用
|
6月前
|
前端开发
基于jeecgboot的flowable流程设计器的用户选择问题修复
基于jeecgboot的flowable流程设计器的用户选择问题修复
89 1
|
6月前
基于jeecgboot的flowable流程综合会签功能演示平台已经发布
基于jeecgboot的flowable流程综合会签功能演示平台已经发布
47 0
|
6月前
基于jeecgboot的flowable流程设计器的几个bug修复
基于jeecgboot的flowable流程设计器的几个bug修复
66 0
api一键自动合约跟单模式 | 程序化交易系统开发讲解【附样板源码实例分析】
“量化交易”有着两层含义:一是从狭义上来讲,是指量化交易的内容,将交易条件转变成为程序,自动下单;二是从广义上来讲,是指系统交易方法,就是一个整合的交易系统。
|
6月前
|
安全 前端开发 Java
针对 SpringSecurity 鉴权流程做了一个详细分析,让你明白它是如何执行的!
针对 SpringSecurity 鉴权流程做了一个详细分析,让你明白它是如何执行的!
282 0
|
安全 Java 数据库
深入Spring Security魔幻山谷-获取认证机制核心原理讲解(新版)
在神秘的Web系统世界里,有一座名为Spring Security的山谷,它高耸入云,蔓延千里,鸟飞不过,兽攀不了。这座山谷只有一条逼仄的道路可通。然而,若要通过这条道路前往另一头的世界,就必须先拿到一块名为token的令牌,只有这样,道路上戍守关口的士兵才会放行。
49 0
下一篇
无影云桌面