使用Camunda流程引擎開發(fā),產(chǎn)品提出根據(jù)流程節(jié)點篩選數(shù)據(jù)需求,...

在用Camunda流程引擎做業(yè)務(wù)開發(fā),遇到了各種各樣的需求,我扣掉了十根頭發(fā),看了很多的星星。今天產(chǎn)品經(jīng)理不知道吃了什么大米,來到的的位置,說:周周同學(xué),我發(fā)現(xiàn)了一個很棒的需求,你要不要聽一聽?
看著產(chǎn)品經(jīng)理一臉壞笑,正要拒絕,產(chǎn)品經(jīng)理繼續(xù)說道:在流程列表頁面,增加一個根據(jù)流程節(jié)點的篩選條件,這樣用戶查詢的時候是不是更加精準(zhǔn)了,我們的系統(tǒng)是不是又完美了很多。我剛要張嘴,產(chǎn)品經(jīng)理電話響了,是客戶的電話。我在一旁就聽產(chǎn)品經(jīng)理吧啦吧啦,大約10分鐘過后。產(chǎn)品經(jīng)理說:剛剛給客戶介紹了這個需求,客戶非常滿意,你今天做好,明天測試,后天就更新到客戶系統(tǒng)。說完拍拍我的肩膀,頭也不回地走了。看著產(chǎn)品經(jīng)理越來越小的背影,感覺腦后吹過一陣涼風(fēng)。我是誰,我在哪里,我要做什么……經(jīng)過一番思緒整理,不就是增加一個流程節(jié)點的列表接口嗎?我做還不行嘛,就這樣我又……思路整理:
- 根據(jù)流程實例ID,獲取流程實例 ? ?根據(jù)流程實例ID,取到定義流程的XML
- 解析流程實例 ? 把XML中的userTask節(jié)點解析
- 返回列表數(shù)據(jù) ? 把解析出來的節(jié)點信息(節(jié)點ID,節(jié)點名字)組裝到LIST返給前端 ? ? ? ? ?

翻看了 Camunda 源碼,發(fā)現(xiàn)真的可以優(yōu)化,接著有了下面的代碼:
返回給前端的節(jié)點數(shù)據(jù)實體:
package com.bpm.camunda.vo;import lombok.Data;public class ActivityNodeVO {// 節(jié)點IDprivate String activityId;// 節(jié)點名字private String activityName;}
??接口層:
public ResponseStatusDto> getActivityNodeList(String procId){
if(StringUtils.isBlank(procId)){return ResponseStatusDto.failure("流程實例ID不能為空");}return ResponseStatusDto.success(workflowTaskService.getActivityNodeList(procId));}
服務(wù)層:
public ListgetActivityNodeList(String procId) { ListactivityNodeVOList = new ArrayList<>(); if(StringUtils.isBlank(procId)){return activityNodeVOList;}HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();if(ObjectUtils.isEmpty(historicProcessInstance)){return activityNodeVOList;}BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(historicProcessInstance.getProcessDefinitionId());if(ObjectUtils.isEmpty(bpmnModelInstance)){return activityNodeVOList;}ListdomElementList = bpmnModelInstance.getDocument().getRootElement().getChildElements(); if(ObjectUtils.isEmpty(domElementList)){return activityNodeVOList;}DomElement domElement = domElementList.stream().filter(it -> "process".equals(it.getLocalName())).findFirst().orElse(null);if(ObjectUtils.isEmpty(domElement)){return activityNodeVOList;}activityNodeVOList.addAll(ActivityNodeUtils.createActivityNodeBySubProcessElement(domElement));return activityNodeVOList;}
涉及到的工具類:
package com.bpm.utils;import com.bpm.camunda.vo.ActivityNodeVO;import org.camunda.bpm.engine.runtime.ActivityInstance;import org.camunda.bpm.model.xml.instance.DomElement;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;public class ActivityNodeUtils {protected static ActivityNodeVO createActivityNodeByTaskElement(DomElement e){ActivityNodeVO activityNodeVO = new ActivityNodeVO();activityNodeVO.setActivityId(e.getAttribute("id"));activityNodeVO.setActivityName(e.getAttribute("name"));return activityNodeVO;}protected static SetgetNodeByActivityInstance(ActivityInstance activityInstance) {if(activityInstance == null){return new HashSet<>();}SetactivityNodeVOSet = new HashSet<>(); ActivityNodeVO activityNodeVO = new ActivityNodeVO();activityNodeVO.setActivityId(activityInstance.getActivityId());activityNodeVO.setActivityName(activityInstance.getActivityName());activityNodeVOSet.add(activityNodeVO);if(ObjectUtils.isNotEmpty(activityInstance.getChildActivityInstances())){for (ActivityInstance instance : activityInstance.getChildActivityInstances()){getNodeByActivityInstance(instance);}}return activityNodeVOSet;}public static ListcreateActivityNodeBySubProcessElement(DomElement e) {ListactivityNodeVOList = new ArrayList<>(); e.getChildElements().stream().filter(it -> "userTask".equals(it.getLocalName()) || "subProcess".equals(it.getLocalName())).forEach(item ->{switch (item.getLocalName()){case "userTask":activityNodeVOList.add(createActivityNodeByTaskElement(item));break;case "subProcess":activityNodeVOList.addAll(createActivityNodeBySubProcessElement(item));break;}});return activityNodeVOList;}}
完成后,調(diào)用接口測試:

完成功能,下班回家。本來加班應(yīng)該有點沮喪,但不知道為什么心里還是有點竊喜,可能這就是做為一名程序的快樂吧!
評論
圖片
表情
