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就會當作變量傳進去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章