activiti多实例设置(会签/或签)

activiti多实例设置(会签/或签)

项目地址:activiti-workflow
在审批流中会遇到会签/或签的情况,activiti本身就已经支持,通过多实例来实现。

本文通过流程画布和Java代码两中方式来作实现。
1.流程画布设置多实例

在这里插入图片描述
设置如图,会计这个节点是会签节点。
参数说明:

  1. Multi-instance-type:多人审批方式 paraller 并行,Sequential 串行,多实例需设置未并行

  2. Execution-listrners:监听器,通过监听类设置Collection中集合的值。监听器的设置可以看之前的博客。

  3. Collection:审批人集合

  4. Element varible:迭代集合(Collection)变量

  5. Completion condition:完成条件(表达式)比如:${nrOfCompletedInstances/nrOfInstances >= 0.5} 。
    nrOfInstances:实例总数
    nrOfActiveInstances:当前活动的,还没完成的实例数量。 对于顺序执行的多实例,值一直为1。
    nrOfCompletedInstances:已经完成实例的数目。

  6. Assignents:审批人(表达式),取 Element varible的值,比如Element varible设置为assignee,Assignents就设置为${assignee}

导出的bpmn文件如图:
在这里插入图片描述

2.通过JAVA类设置
这种方式使用为通过JAVA类生成流程定义数据

//用户节点
UserTask userTask = new UserTask();
MultiInstanceLoopCharacteristics  multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();  
//审批人集合参数
multiInstanceLoopCharacteristics.setInputDataItem("assigneeList");
//迭代集合
multiInstanceLoopCharacteristics.setElementVariable("assignee");
//完成条件 已完成数等于实例数
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfActiveInstances == nrOfInstances}");
//并行
multiInstanceLoopCharacteristics.setSequential(false);
taskNode.setAssignee("${assignee}");
//设置多实例属性
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
//设置监听器
taskNode.setExecutionListeners(countersignTaskListener());
//设置审批人
taskNode.setCandidateUsers(candidateUser);

candidateUser为审批人集合,用户在设计流程是指定。CompletionCondition设置已审批数量等于实例总数(会签)。

这里需要注意一下,当用户节点设置了多实例属性后,设置监听器时是设置executionListeners而不是taskListeners。类要实现ExecutionListener或者JavaDelegate,普通用户节点实现TaskListener。还有多实例属性中loopCardinality和inputDataItem两个必须设置一个,这个在部署流程似有校验
校验在这里

org.activiti.validation.validator.impl.FlowElementValidator#handleMultiInstanceLoopCharacteristics多实例检验(检验loopCardinality和inputDataItem),校验不通过会抛出异常。

	protected void handleMultiInstanceLoopCharacteristics(Process process, Activity activity, List<ValidationError> errors) {
    
    
		MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();
		if (multiInstanceLoopCharacteristics != null) {
    
    

			if (StringUtils.isEmpty(multiInstanceLoopCharacteristics.getLoopCardinality())
	    		&& StringUtils.isEmpty(multiInstanceLoopCharacteristics.getInputDataItem())) {
    
    
	    	
			  addError(errors, Problems.MULTI_INSTANCE_MISSING_COLLECTION, process, activity,
	    			"Either loopCardinality or loopDataInputRef/activiti:collection must been set");
	    }

		}
	}

多实例监听器设置如下

ArrayList<ActivitiListener> listener = new ArrayList<>();
ActivitiListener activitiListener = new ActivitiListener();
 //事件类型,
activitiListener.setEvent(ExecutionListener.EVENTNAME_START);
//监听器类型
activitiListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
//设置实现了,这里设置监听器的类型是delegateExpression,这样可以在实现类注入Spring bean.
activitiListener.setImplementation("${multiInstanceTaskHandler}");
listener.add(activitiListener);

监听器类型说明:
class :java类的全路径,类需实现 TaskListener,会执行notify()方法,这种实现类不能注入Spring bean
expression :执行特定类的特定方法 配置 :${test.test()}
delegateExpression:配置spring的bean,${test}。实现类交由spring管理。

监听类实现

@Slf4j
@Component
public class MultiInstanceTaskHandlerimplements ExecutionListener {
    
    
    @Override
    public void notify(DelegateExecution delegateTask) {
    
    
        log.info("任务监听类开始执行");
        FlowElement currentFlowElement = delegateTask.getCurrentFlowElement();
        if(currentFlowElement instanceof UserTask){
    
    
            UserTask userTask = (UserTask) currentFlowElement;
            List<String> candidateUsers = userTask.getCandidateUsers();
            //设为本地变量(节点所有)
            delegateTask.setVariableLocal("assigneeList",candidateUsers);
        }
    }
}

这样在多实例节点创建时,assigneeList就会当作变量传进去。

猜你喜欢

转载自blog.csdn.net/qq_34758074/article/details/103330904