java調用Activiti實現二次開發


activiti發展到現在,發布版本已經到7了。Activiti項目是一項新的基於Apache許可的開源BPM平台,從基礎開始構建,旨在提供支持新的BPMN 2.0標准,包括支持對象管理組(OMG),可以定義流程、執行流程並以不同方式對其實現運行。

一、activiti數據庫表結構說明

表名默認以“ACT_”開頭,並且表名的第二部分用兩個字母表明表的用例,而這個用例也基本上跟Service API匹配。

ACT_GE_* : “GE”代表“General”(通用),用在各種情況下;

ACT_HI_* : “HI”代表“History”(歷史),這些表中保存的都是歷史數據,比如執行過的流程實例、變量、任務,等等。Activit默認提供了4種歷史級別:

ACT_RE_* : “RE”代表“Repository”(倉庫),這些表中保存一些‘靜態’信息,如流程定義和流程資源(如圖片、規則等);

ACT_RU_* : “RU”代表“Runtime”(運行時),這些表中保存一些流程實例、用戶任務、變量等的運行時數據。Activiti只保存流程實例在執行過程中的運行時數據,並且當流程結束后會立即移除這些數據;

表分類 表名稱 表含義
資源庫流程規則表 act_re_deployment 部署信息表
act_re_model 流程設計模型部署表
act_re_procdef  流程定義數據表
流程歷史記錄 act_hi_actinst  歷史的流程實例
act_hi_attachment  歷史的流程附件
act_hi_comment 歷史的說明性信息
act_hi_detail  歷史的流程運行中的細節信息
act_hi_identitylink  歷史的流程運行過程中用戶關系
act_hi_procinst 歷史的流程實例
act_hi_taskinst  歷史的任務實例
act_hi_varinst  歷史的流程運行中的變量信息
流程運行實例記錄 act_ru_deadletter_job  執行失敗任務表
act_ru_integration 運行時流程人員表,主要存儲任務節點與參與者的相關信息
act_ru_event_subscr  運行時事件
act_ru_execution  運行時流程執行實例
act_ru_identitylink  運行時用戶關系信息
act_ru_job  運行時作業
act_ru_suspended_job  運行時暫停任務
act_ru_task  運行時任務
act_ru_timer_job  運行時定時任務
act_ru_variable  運行時變量表
通用數據表 act_ge_bytearray           二進制數據表
act_ge_property             屬性數據表存儲整個流程引擎級別的數據,初始化表結構時,會默認插入三條記錄

二、activiti提供服務的七大對象

RepositoryService: Activiti 中每一個不同版本的業務流程的定義都需要使用一些定義文件,部署文件和支持數據 ( 例如 BPMN2.0 XML 文件,表單定義文件,流程定義圖像文件等 ),這些文件都存儲在 Activiti 內建的 Repository 中。Repository Service 提供了對 repository 的存取服務。
RuntimeService: 在 Activiti 中,每當一個流程定義被啟動一次之后,都會生成一個相應的流程對象實例。Runtime Service 提供了啟動流程、查詢流程實例、設置獲取流程實例變量等功能。此外它還提供了對流程部署,流程定義和流程實例的存取服務。
TaskService: 在 Activiti 中業務流程定義中的每一個執行節點被稱為一個 Task,對流程中的數據存取,狀態變更等操作均需要在 Task 中完成。Task Service 提供了對用戶 Task 和 Form 相關的操作。它提供了運行時任務查詢、領取、完成、刪除以及變量設置等功能。
IdentityService: Activiti 中內置了用戶以及組管理的功能,必須使用這些用戶和組的信息才能獲取到相應的 Task。Identity Service 提供了對 Activiti 系統中的用戶和組的管理功能。
ManagementService: Management Service 提供了對 Activiti 流程引擎的管理和維護功能,這些功能不在工作流驅動的應用程序中使用,主要用於 Activiti 系統的日常維護。
HistoryService: Activiti 中的流程和狀態 Task 均可以關聯業務相關的數據。通過使用 Form Service 可以存取啟動和完成任務所需的表單數據並且根據需要來渲染表單。
FormService: Activiti 中的流程和狀態 Task 均可以關聯業務相關的數據。通過使用 Form Service 可以存取啟動和完成任務所需的表單數據並且根據需要來渲染表單。

三、java封裝實例

1、前端界面效果圖

2、二次開發類圖

3、代碼展示

  如下是具體實現的類信息,當前實例封裝的是通過具體人和人員角色兩個維度來實現業務節點審核,要實現業務功能只需要實現BaseBusinessActivitiOption類的方法,並擴充業務實現就好。

1)NumrangeEntity 審核流條件表達式類,用於記錄審核流條件分支的條件信息

  1 public class NumrangeEntity {
  2 
  3     public NumrangeEntity(){}
  4 
  5     public NumrangeEntity(String expression){
  6         expression = expression.replace("${","").replace("}","");
  7         if(expression.contains("&&")){
  8             String[] branchExpression = expression.split("&&");
  9             String[] params = expressionBackwardAnalysis(branchExpression[0]);
 10             this.variable = params[0];
 11             this.minValue = Double.parseDouble(params[2]);
 12             params = expressionBackwardAnalysis(branchExpression[1]);
 13             this.maxValue = Double.parseDouble(params[2]);
 14             this.op = "6";
 15         }else{
 16             String[] params = expressionBackwardAnalysis(expression);
 17             this.variable = params[0];
 18             this.op = params[1];
 19             this.value = Double.parseDouble(params[2]);
 20         }
 21 
 22         getConditionName();
 23     }
 24 
 25     private String[] expressionBackwardAnalysis(String expression){
 26         String[] params = expression.split(" ");
 27         switch(params[1]){
 28             case "==":
 29                 params[1] = "1";
 30                 break;
 31             case ">":
 32                 params[1] = "2";
 33                 break;
 34             case "<":
 35                 params[1] = "3";
 36                 break;
 37             case ">=":
 38                 params[1] = "4";
 39                 break;
 40             case "<=":
 41                 params[1] = "5";
 42                 break;
 43         }
 44 
 45         return params;
 46     }
 47 
 48     /**
 49      * 操作類型:1-等於;2-大於;3-小於;4-大於等於;5-小於等於;6-介於
 50      */
 51     private String op;
 52 
 53     /**
 54      *比較值
 55      */
 56     private double value;
 57 
 58     /**
 59      * 區間最小值
 60      */
 61     private double minValue;
 62 
 63     /**
 64      * 區間最大值
 65      */
 66     private double maxValue;
 67 
 68     private String variable;
 69 
 70     private String conditionName;
 71 
 72     public String getOp() {
 73         return op;
 74     }
 75 
 76     public String getExpression(){
 77         StringBuffer expression = new StringBuffer();
 78         expression.append("${");
 79         switch(op){
 80             case "1#等於":
 81                 expression.append(variable + " == " + value);
 82                 break;
 83             case "2#大於":
 84                 expression.append(variable + " > " + value);
 85                 break;
 86             case "3#小於":
 87                 expression.append(variable + " < " + value);
 88                 break;
 89             case "4#大於等於":
 90                 expression.append(variable + " >= " + value);
 91                 break;
 92             case "5#小於等於":
 93                 expression.append(variable + " <= " + value);
 94                 break;
 95             case "6#介於":
 96                 expression.append(variable + " > " + minValue + "&&" + variable + " < " + maxValue);
 97                 break;
 98         }
 99 
100         expression.append("}");
101 
102         return expression.toString();
103     }
104 
105     public void getConditionName(){
106         StringBuffer name = new StringBuffer();
107         name.append(Variable.valueOf(variable.toUpperCase()).getText());
108 
109         switch (op){
110             case "1":
111                 name.append("等於");
112                 op = "1#等於";
113                 break;
114             case "2":
115                 name.append("大於");
116                 op = "2#大於";
117                 break;
118             case "3":
119                 name.append("小於");
120                 op = "3#小於";
121                 break;
122             case "4":
123                 name.append("大於等於");
124                 op = "4#大於等於";
125                 break;
126             case "5":
127                 name.append("小於等於");
128                 op = "5#小於等於";
129                 break;
130             case "6":
131                 name.append("介於");
132                 op = "6#介於";
133         }
134         if(op.equals("6#介於")){
135             name.append(minValue);
136             name.append(Variable.valueOf(variable.toUpperCase()).getUnit());
137             name.append("-");
138             name.append(maxValue);
139         }else{
140             name.append(value);
141         }
142 
143         name.append(Variable.valueOf(variable.toUpperCase()).getUnit());
144 
145         conditionName = name.toString();
146     }
147 
148     public void setOp(String op) {
149         this.op = op;
150     }
151 
152     public double getValue() {
153         return value;
154     }
155 
156     public void setValue(double value) {
157         this.value = value;
158     }
159 
160     public double getMinValue() {
161         return minValue;
162     }
163 
164     public void setMinValue(double minValue) {
165         this.minValue = minValue;
166     }
167 
168     public double getMaxValue() {
169         return maxValue;
170     }
171 
172     public void setMaxValue(double maxValue) {
173         this.maxValue = maxValue;
174     }
175 
176     public String getVariable() {
177         return variable;
178     }
179 
180     public void setVariable(String variable) {
181         this.variable = variable;
182     }
183 
184     enum Variable{
185 
186         CONTRACTAMOUNT("contractAmount","合同金額","萬元");
187         Variable(String name,String text,String unit){
188             this.name = name;
189             this.text = text;
190             this.unit = unit;
191         }
192 
193         private String name;
194         private String text;
195         private String unit;
196 
197         public String getName(){
198             return name;
199         }
200 
201         public String getText(){
202             return text;
203         }
204 
205         public String getUnit(){
206             return unit;
207         }
208     }
209 }
View Code

2)TaskNodeEntity 審核流任務節點類,用於記錄審核節點信息

 1 public class TaskNodeEntity {
 2 
 3     public TaskNodeEntity(){}
 4 
 5     public TaskNodeEntity(String nodeType,String nodeTitleName,String nodeTitle,int order){
 6         this.nodeType = nodeType;
 7         this.nodeTitle = nodeTitle;
 8         this.nodeTitleName = nodeTitleName;
 9         this.order = order;
10     }
11 
12     /**
13      * 任務節點類型:role-角色;people-具體人
14      */
15     private String nodeType;
16 
17     /**
18      * 任務節點標題名稱:角色名稱/用戶名稱
19      */
20     private String nodeTitleName;
21 
22     /**
23      * 任務節點標題:角色編碼/用戶ID
24      */
25     private String nodeTitle;
26 
27     /**
28      * 任務節點位置
29      */
30     private int order;
31 
32     public String getNodeType() {
33         return nodeType;
34     }
35 
36     public void setNodeType(String nodeType) {
37         this.nodeType = nodeType;
38     }
39 
40     public String getNodeTitleName() {
41         return nodeTitleName;
42     }
43 
44     public void setNodeTitleName(String nodeTitleName) {
45         this.nodeTitleName = nodeTitleName;
46     }
47 
48     public String getNodeTitle() {
49         return nodeTitle;
50     }
51 
52     public void setNodeTitle(String nodeTitle) {
53         this.nodeTitle = nodeTitle;
54     }
55 
56     public int getOrder() {
57         return order;
58     }
59 
60     public void setOrder(int order) {
61         this.order = order;
62     }
63 
64     @Override
65     public boolean equals(Object obj) {
66         if(this == obj){
67             return true;
68         }
69 
70         if(obj == null){
71             return false;
72         }
73 
74         if(obj instanceof TaskNodeEntity){
75             TaskNodeEntity taskNodeEntity = (TaskNodeEntity) obj;
76             if(equalsStr(this.nodeType,taskNodeEntity.getNodeType()) && equalsStr(this.nodeTitle,taskNodeEntity.getNodeTitle())){
77                 return true;
78             }
79         }
80         return false;
81     }
82 
83     @Override
84     public int hashCode() {
85         return Objects.hash(this.nodeType,this.nodeTitle);
86     }
87 
88     private boolean equalsStr(String str1, String str2){
89         if(StringUtils.isEmpty(str1) && StringUtils.isEmpty(str2)){
90             return true;
91         }
92         if(!StringUtils.isEmpty(str1) && str1.equals(str2)){
93             return true;
94         }
95         return false;
96     }
97 }
View Code

3)RuleEntity 審核流子流程信息類

 1 public class RuleEntity {
 2 
 3     public RuleEntity(){};
 4 
 5     public RuleEntity(String ruleName,String ruleType,NumrangeEntity numrangeitem){
 6         this.ruleName = ruleName;
 7         this.ruleType = ruleType;
 8         this.numrangeitem = numrangeitem;
 9     }
10 
11     /**
12      * 任務節點
13      */
14     private List<TaskNodeEntity> taskNodes;
15 
16     /**
17      * 規則名稱名稱
18      */
19     private String ruleName;
20 
21     /**
22      * 規則類型:default-默認;condition-條件
23      */
24     private String ruleType;
25 
26     /**
27      * 條件參數
28      */
29     private NumrangeEntity numrangeitem;
30 
31     public List<TaskNodeEntity> getTaskNodes() {
32         if(null == taskNodes){
33             return taskNodes = new ArrayList<TaskNodeEntity>();
34         }
35         return taskNodes;
36     }
37 
38     public void setTaskNodes(List<TaskNodeEntity> taskNodes) {
39         this.taskNodes = taskNodes;
40     }
41 
42     public String getRuleName() {
43         return ruleName;
44     }
45 
46     public void setRuleName(String ruleName) {
47         this.ruleName = ruleName;
48     }
49 
50     public String getRuleType() {
51         return ruleType;
52     }
53 
54     public void setRuleType(String ruleType) {
55         this.ruleType = ruleType;
56     }
57 
58     public NumrangeEntity getNumrangeitem() {
59         return numrangeitem;
60     }
61 
62     public void setNumrangeitem(NumrangeEntity numrangeitem) {
63         this.numrangeitem = numrangeitem;
64     }
65 }
View Code

4)ProcessEntity 審核流全流程信息

 1 public class ProcessEntity {
 2 
 3     /**
 4      * 子流程集合
 5      */
 6     private List<RuleEntity> rules;
 7 
 8     /**
 9      * 流程類型:認定、終止合同、廢標、建議刪除
10      */
11     private String processType;
12 
13     /**
14      * 流程類型名稱
15      */
16     private String processTypeName;
17 
18     /**
19      * 所屬機構名稱
20      */
21     private String orgName;
22 
23     /**
24      * 所屬機構編碼
25      */
26     private String orgId;
27 
28     public List<RuleEntity> getRules() {
29         if(null == rules){
30             return rules = new ArrayList<RuleEntity>();
31         }
32         return rules;
33     }
34 
35     public void setRules(List<RuleEntity> rules) {
36         this.rules = rules;
37     }
38 
39     public String getProcessType() {
40         return processType;
41     }
42 
43     public void setProcessType(String processType) {
44         this.processType = processType;
45     }
46 
47     public String getProcessTypeName() {
48         return processTypeName;
49     }
50 
51     public void setProcessTypeName(String processTypeName) {
52         this.processTypeName = processTypeName;
53     }
54 
55     public String getOrgName() {
56         return orgName;
57     }
58 
59     public void setOrgName(String orgName) {
60         this.orgName = orgName;
61     }
62 
63     public String getOrgId() {
64         return orgId;
65     }
66 
67     public void setOrgId(String orgId) {
68         this.orgId = orgId;
69     }
70 }
View Code

5)ApplyDomain 審核流任務節點處理結果實體;ProcessType 審核流類型枚舉

 1 public class ApplyDomain extends PagingDomain{
 2 
 3     @TableField(exist = false)
 4     private String taskId;
 5 
 6     @TableField(exist = false)
 7     private String currentUserCode;
 8 
 9     /**
10      * 審核狀態:init-審核中;pass-通過;fail-不通過
11      */
12     @TableField("examination_status")
13     private String examinationStatus;
14 
15     public String getTaskId() {
16         return taskId;
17     }
18 
19     public void setTaskId(String taskId) {
20         this.taskId = taskId;
21     }
22 
23     public String getCurrentUserCode() {
24         return currentUserCode;
25     }
26 
27     public void setCurrentUserCode(String currentUserCode) {
28         this.currentUserCode = currentUserCode;
29     }
30 
31     public String getExaminationStatus() {
32         return examinationStatus;
33     }
34 
35     public void setExaminationStatus(String examinationStatus) {
36         this.examinationStatus = examinationStatus;
37     }
38 }
View Code
 1 public enum ProcessType {
 2     RENDING("rending","項目認定"),
 3     SHANCHU("shanchu","建議刪除"),
 4     PROJECTADD("projectAdd","項目添加"),
 5     PROJECTEDITOR("projectEditor","項目編輯"),
 6     ZHONGZHI("zhongzhi","項目中止"),
 7     YICHANG("yichang","項目異常"),
 8     YIJIAO("yijiao","項目移交");
 9 
10 
11     ProcessType(String type,String typeName){
12         this.type = type;
13         this.typeName = typeName;
14     }
15 
16     private String type;
17 
18     private String typeName;
19 
20     public String getType() {
21         return type;
22     }
23 
24     public String getTypeName() {
25         return typeName;
26     }
27 }
View Code

6)ActivitiOption 審核流流程操作類,提供了七大服務類的操作

  1 @Component
  2 public class ActivitiOption {
  3 
  4     @Autowired
  5     private RepositoryService repositoryService;
  6 
  7     @Autowired
  8     private RuntimeService runtimeService;
  9 
 10     @Autowired
 11     private HistoryService historyService;
 12 
 13     @Autowired
 14     private TaskService taskService;
 15 
 16     protected void findAllProcess(Set<String> set){
 17         List<ProcessDefinition> definitions = repositoryService
 18                 .createProcessDefinitionQuery()
 19                 .processDefinitionKeys(set)
 20                 .latestVersion()
 21                 .orderByProcessDefinitionVersion()
 22                 .desc()
 23                 .list();
 24     }
 25 
 26     /**
 27      * Description:獲取流程定義
 28      * Param:
 29      * Return:
 30      * Auther: cymiao
 31      * Date: 2019/9/26 14:01
 32      */
 33     protected ProcessEntity findProcess(String orgId,String processType,String processTypeName){
 34         //通過流程Key獲取流程定義對象
 35         ProcessDefinition definition = repositoryService
 36                 .createProcessDefinitionQuery()
 37                 .processDefinitionKey(getProcessKey(orgId, processType))
 38                 .latestVersion()
 39                 .singleResult();
 40 
 41         if(null == definition){
 42             throw new BusinessBaseException(new BusinessExceptionDesc("3002001", BusinessExceptionDesc.SHOW_TYPE.ERROR,"當前查詢的機構沒有定義" + processTypeName + "類型的審核流"));
 43         }
 44 
 45         //獲取流程下的所有節點
 46         List<FlowElement> flowElements = (List<FlowElement>) repositoryService
 47                 .getBpmnModel(definition.getId())
 48                 .getProcesses()
 49                 .get(0)
 50                 .getFlowElements();
 51 
 52         //反向解析
 53         ProcessEntity processInfo = new ProcessEntity();
 54         bpmnBackwardAnalysis(flowElements,processInfo);
 55         return processInfo;
 56     }
 57 
 58     /**
 59      * Description:反向解析BpmnModel
 60      * Param:
 61      * Return:
 62      * Auther: cymiao
 63      * Date: 2019/9/26 14:02
 64      */
 65     protected void bpmnBackwardAnalysis(List<FlowElement> flowElements,ProcessEntity processInfo){
 66         for (FlowElement flowElement : flowElements){
 67             if(flowElement instanceof SequenceFlow){
 68                 FlowElement sourceFlowElement = ((SequenceFlow) flowElement).getSourceFlowElement();
 69                 if(sourceFlowElement.getId().equals("start")){
 70                     FlowElement targetFlowElement = ((SequenceFlow) flowElement).getTargetFlowElement();
 71                     //開始節點的下一個節點,如果為網關則是條件網關
 72                     if(targetFlowElement instanceof ExclusiveGateway){
 73                         ExclusiveGateway gateway = (ExclusiveGateway) targetFlowElement;
 74                         List<SequenceFlow> flows = gateway.getOutgoingFlows();
 75                         for(SequenceFlow flow : flows){
 76                             //${money > 300}
 77                             String conditionExpression = flow.getConditionExpression();
 78 
 79                             //分支流程
 80                             RuleEntity rule = null;
 81                             if(flow.getId().equals(gateway.getDefaultFlow())){
 82                                 rule = new RuleEntity(flow.getName(),"default",null);
 83                             }else{
 84                                 //分支條件
 85                                 NumrangeEntity numrangeEntity = new NumrangeEntity(conditionExpression);
 86                                 rule = new RuleEntity(flow.getName(),"condition",numrangeEntity);
 87                             }
 88 
 89 
 90                             processInfo.getRules().add(rule);
 91 
 92                             sequenceFlowBackwardAnalysis(flow.getTargetFlowElement(),rule,1);
 93                         }
 94                     }/*
 95                     //開始節點的下一個節點是任務節點
 96                     else if(targetFlowElement instanceof UserTask){
 97                         RuleEntity rule = new RuleEntity(flowElement.getName(),"",null);
 98                         sequenceFlowBackwardAnalysis(targetFlowElement,rule,1);
 99                     }*/
100                 }
101                 break;
102             }
103         }
104     }
105 
106     /**
107      * Description:反向解析任務節點
108      * Param:
109      * Return:
110      * Auther: cymiao
111      * Date: 2019/9/26 14:02
112      */
113     protected void sequenceFlowBackwardAnalysis(FlowElement flowElement,RuleEntity rule,int order){
114         if(flowElement instanceof UserTask){
115             UserTask userTask = (UserTask) flowElement;
116             String taskId = userTask.getId();
117             if(taskId.lastIndexOf("-") > 0){
118                 String suffiz = taskId.substring(taskId.lastIndexOf("-"));
119                 taskId = taskId.replace(suffiz,"");
120             }
121 
122             //節點類型
123             String nodeType = taskId.contains("people") ? "people" : "role";
124 
125             //節點標題
126             String nodeTitle = taskId.replace(nodeType,"");
127 
128             //節點實例 
129             TaskNodeEntity nodeEntity = new TaskNodeEntity(nodeType,userTask.getName(),nodeTitle,order);
130             rule.getTaskNodes().add(nodeEntity);
131 
132             //下一個節點對象
133             FlowElement nextFlowElement1 = userTask
134                     .getOutgoingFlows()
135                     .get(0)
136                     .getTargetFlowElement();
137 
138             //下一個節點存在,並且是網關節點
139             if(null != nextFlowElement1 && nextFlowElement1 instanceof ExclusiveGateway){
140                 ExclusiveGateway switchGateway = (ExclusiveGateway)nextFlowElement1;
141                 List<SequenceFlow> flows = switchGateway.getOutgoingFlows();
142                 for (SequenceFlow flow : flows){
143                     //下一個任務節點
144                     if(flow.getTargetFlowElement() instanceof UserTask){
145                         sequenceFlowBackwardAnalysis(flow.getTargetFlowElement(),rule, ++order);
146                     }
147                 }
148             }
149             //下一個節點是結束事件節點
150             else if(null != nextFlowElement1 && nextFlowElement1 instanceof EndEvent){
151                 return;
152             }
153         }
154     }
155 
156     /**
157      * Description:獲取子流程的歷史任務
158      * Param:
159      * Return:
160      * Auther: cymiao
161      * Date: 2019/9/25 17:34
162      */
163     protected List<HistoricActivityInstance> findProcessHistoryByStartTime(String processInstanceId){
164         List<HistoricActivityInstance> his = historyService
165                 .createHistoricActivityInstanceQuery()
166                 .processInstanceId(processInstanceId)
167                 .orderByHistoricActivityInstanceStartTime().asc().list();
168         return his;
169     }
170 
171     /**
172      * Description:發布部署
173      * Param:
174      * Return:
175      * Auther: cymiao
176      * Date: 2019/9/17 19:43
177      */
178     protected void deployDeployment(ProcessEntity processInfo){
179         BpmnModel bpmnModel = new BpmnModel();
180         bpmnModel.addProcess(createProcess(processInfo));
181 
182         //驗證Bpmn文件的可用性
183         ProcessValidatorFactory processValidatorFactory = new ProcessValidatorFactory();
184         ProcessValidator processValidator = processValidatorFactory.createDefaultProcessValidator();
185         List<ValidationError> validate = processValidator.validate(bpmnModel);
186         if(validate.size()>=1){
187             for (ValidationError validationError : validate) {
188                 System.out.println(validationError.getProblem());
189                 throw new BusinessBaseException(new BusinessExceptionDesc("", BusinessExceptionDesc.SHOW_TYPE.ERROR,"配置項錯誤,審核流不可用"));
190             }
191         }
192 
193         BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
194         try {
195             String e = new String(bpmnXMLConverter.convertToXML(bpmnModel), "UTF-8");
196             System.out.println(e);
197         } catch (UnsupportedEncodingException var5) {
198             throw new ActivitiException("Error while transforming BPMN model to xml: not UTF-8 encoded", var5);
199         }
200 
201         //創建一個部署對象
202         repositoryService.createDeployment()
203                 .addBpmnModel("org" + processInfo.getOrgId() + processInfo.getProcessType() + ".bpmn",bpmnModel)
204                 .name(processInfo.getOrgName() + processInfo.getProcessTypeName())
205                 .deploy();
206     }
207 
208     /**
209      * Description:創建流程實例
210      * Param:
211      * Return:
212      * Auther: cymiao
213      * Date: 2019/9/19 18:50
214      */
215     protected String startProcessInstance(String orgId,String processType,String businessId,Map<String,Object> variables){
216         String processInstanceKey = "org" + orgId + processType;
217         ProcessInstance  pi = runtimeService
218                 .startProcessInstanceByKey(processInstanceKey,processType + "-" + businessId,variables);
219         return pi.getProcessInstanceId();
220     }
221 
222     /**
223      * Description:任務審核結束
224      * Param:
225      * Return:
226      * Auther: cymiao
227      * Date: 2019/9/20 9:39
228      */
229     protected void taskComplete(String taskid,String examineUser, Map<String,Object> variables){
230         taskService.claim(taskid, examineUser);
231         taskService.complete(taskid, variables);
232     }
233 
234     /**
235      * Description:通過任務Id獲取流程實例Id
236      * Param:
237      * Return:
238      * Auther: cymiao
239      * Date: 2019/9/24 18:18
240      */
241     protected String findProcessInstanceIdByTaskId(String taskid){
242         String processInstanceId = taskService
243                 .createTaskQuery()
244                 .taskId(taskid)
245                 .singleResult()
246                 .getProcessInstanceId();
247         return processInstanceId;
248     }
249 
250     /**
251      * Description:通過角色查詢某一類型的待辦任務
252      * Param:
253      * Return:
254      * Auther: cymiao
255      * Date: 2019/9/20 15:23
256      */
257     protected List<Task> findRoleTasks(String processKey,String roleCode){
258         List<Task> tasks = taskService
259                 .createTaskQuery()
260                 .processDefinitionKey(processKey)
261                 .taskCandidateGroup(roleCode)
262                 .list();
263         return tasks;
264     }
265 
266     /**
267      * Description:通過角色查詢某一類型的待辦任務的數量
268      * Param:
269      * Return:
270      * Auther: cymiao
271      * Date: 2019/9/20 15:24
272      */
273     protected int findRoleTasksCount(String processKey,String roleCode){
274         int totaltask = (int)taskService.createTaskQuery().processDefinitionKey(processKey).taskCandidateGroup(roleCode).count();
275         return totaltask;
276     }
277 
278     /**
279      * Description:通過角色查詢所有的待辦任務
280      * Param:
281      * Return:
282      * Auther: cymiao
283      * Date: 2019/9/20 15:23
284      */
285     protected List<Task> findRoleTasks(String roleCode,int firstrow,int rowCount){
286         List<Task> tasks = taskService
287                 .createTaskQuery()
288                 .taskCandidateGroup(roleCode)
289                 .listPage(firstrow, rowCount);
290         return tasks;
291     }
292 
293     /**
294      * Description:通過角色查詢所有的待辦任務的數量
295      * Param:
296      * Return:
297      * Auther: cymiao
298      * Date: 2019/9/20 15:25
299      */
300     protected int findRoleTasksCount(String roleCode){
301         int totaltask = (int)taskService
302                 .createTaskQuery()
303                 .taskCandidateGroup(roleCode)
304                 .count();
305         return totaltask;
306     }
307 
308     /**
309      * Description:通過用戶ID查詢某一類型的待辦任務
310      * Param:
311      * Return:
312      * Auther: cymiao
313      * Date: 2019/9/20 15:26
314      */
315     protected List<Task> findUserTasks(String processKey,String userCode){
316         List<Task> tasks = taskService
317                 .createTaskQuery()
318                 .processDefinitionKey(processKey)
319                 .taskCandidateUser(userCode)
320                 .list();
321         return tasks;
322     }
323 
324     protected List<Task> findUserTasks(List<String> processKeys,String userCode){
325         List<Task> tasks = taskService
326                 .createTaskQuery()
327                 .processDefinitionKeyIn(processKeys)
328                 .taskCandidateUser(userCode)
329                 .list();
330         return tasks;
331     }
332 
333     /**
334      * Description:通過用戶ID查詢某一類型的待辦任務的數量
335      * Param:
336      * Return:
337      * Auther: cymiao
338      * Date: 2019/9/20 15:27
339      */
340     protected int findUserTasksCount(String processKey,String userCode){
341         int totaltask = (int)taskService
342                 .createTaskQuery()
343                 .processDefinitionKey(processKey)
344                 .taskCandidateUser(userCode)
345                 .count();
346         return totaltask;
347     }
348 
349     /**
350      * Description:通過用戶ID查詢所有的待辦任務
351      * Param:
352      * Return:
353      * Auther: cymiao
354      * Date: 2019/9/20 15:28
355      */
356     protected List<Task> findUserTasks(String userCode){
357         List<Task> tasks = taskService
358                 .createTaskQuery()
359                 .taskCandidateUser(userCode)
360                 .list();
361         return tasks;
362     }
363 
364     /**
365      * Description:通過用戶ID查詢所有的待辦任務數量
366      * Param:
367      * Return:
368      * Auther: cymiao
369      * Date: 2019/9/20 15:29
370      */
371     protected int findUserTasksCount(String userCode){
372         int totaltask = (int)taskService
373                 .createTaskQuery()
374                 .taskCandidateUser(userCode)
375                 .count();
376         return totaltask;
377     }
378 
379     /**
380      * Description:獲取流程Id
381      * Param:
382      * Return:
383      * Auther: cymiao
384      * Date: 2019/9/20 16:00
385      */
386     protected String getProcessKey(String orgId,String processType){
387         return "org" + orgId + processType;
388     }
389 
390     /**
391      * Description:通過工作流實例ID獲取業務主鍵
392      * Param:
393      * Return:
394      * Auther: cymiao
395      * Date: 2019/9/20 16:02
396      */
397     public String findBusinesskeyByProcessInstanceId(String processInstanceId){
398         String businesskey = runtimeService.
399                 createProcessInstanceQuery()
400                 .processInstanceId(processInstanceId)
401                 .singleResult()
402                 .getBusinessKey();
403         return businesskey;
404     }
405 
406     /**
407      * Description:創建流程
408      * Param:
409      * Return:
410      * Auther: cymiao
411      * Date: 2019/9/17 19:43
412      */
413     protected Process createProcess(ProcessEntity processInfo){
414 
415         FlowElement previousFlowElement = null;
416         Process process = new Process();
417 
418         //ID:org + 組織機構ID + 流程類型
419         process.setId("org" + processInfo.getOrgId() + processInfo.getProcessType());
420 
421         //NAME:組織機構名稱 + 流程類型名稱
422         process.setName(processInfo.getOrgName() + processInfo.getProcessTypeName());
423 
424         //添加開始事件
425         FlowElement startEvent = createStartEvent();
426         process.addFlowElement(startEvent);
427 
428         //創建異常結束事件
429         FlowElement abnormalEndEvent = createEndEvent("abnormalEnd","異常結束",true);
430         process.addFlowElement(abnormalEndEvent);
431 
432         //添加結束事件
433         FlowElement endEvent = createEndEvent("end","結束",false);
434         process.addFlowElement(endEvent);
435 
436         List<RuleEntity> rules = processInfo.getRules();
437         if(null == rules || rules.isEmpty()){
438             throw new BusinessBaseException(new BusinessExceptionDesc("", BusinessExceptionDesc.SHOW_TYPE.ERROR,"審核流程不能空"));
439         }else{
440             List<TaskNodeEntity> taskNodes = null;
441             //審核通過和不通過判斷表達式
442             String examinationPass = "${examinationStatus == 'pass'}";
443             String examinationNotPass = "${examinationStatus == 'fail'}";
444 
445             //創建條件網關
446             ExclusiveGateway conditionExclusiveGateway = null;
447             process.addFlowElement(conditionExclusiveGateway = createExclusiveGateway("條件判斷網關","condition"));
448 
449             //創建連線:流程開始節點到條件網關的連線
450             SequenceFlow sequenceFlow = genarateSequenceFlow("flow1","網關",startEvent.getId(),conditionExclusiveGateway.getId(),"",process);
451             process.addFlowElement(sequenceFlow);
452             conditionExclusiveGateway.getOutgoingFlows().add(sequenceFlow);
453 
454             for (int i = 0; i < rules.size(); i++){
455                 previousFlowElement = conditionExclusiveGateway;
456                 RuleEntity rule = rules.get(i);
457 
458                 //創建子流程
459                 taskNodes = rule.getTaskNodes();
460 
461                 //規則重排序
462                 Collections.sort(taskNodes, new Comparator<TaskNodeEntity>() {
463                     @Override
464                     public int compare(TaskNodeEntity o1, TaskNodeEntity o2) {
465                         if(o1.getOrder() > o2.getOrder()){
466                             return 1;
467                         }else{
468                             return -1;
469                         }
470                     }
471                 });
472                 UserTask userTask = null;
473                 for (int j = 0; j < taskNodes.size(); j++){
474                     TaskNodeEntity taskNode = taskNodes.get(j);
475                     String taskId = taskNode.getNodeType() + taskNode.getNodeTitle() + "-" + rule.getRuleType() + i;
476 
477                     //創建任務
478                     userTask = createUserTask(taskNode.getNodeTitleName(),taskId,taskNode.getNodeType(),taskNode.getNodeTitle());
479                     process.addFlowElement(userTask);
480 
481                     //創建通過和不通過分支網關
482                     ExclusiveGateway switchGateway = createExclusiveGateway("分支網關","switchGateway" + (i + 1)  + (j + 1));
483                     process.addFlowElement(switchGateway);
484 
485                     //創建當前節點到分支網關的連線
486                     process.addFlowElement(genarateSequenceFlow("flow1-" + (i + 1)  + (j + 1),"到達分支",taskId,switchGateway.getId(),"",process));
487 
488                     //創建連線:上一個節點到當前節點的連線
489                     if(j == 0){
490                         //條件網關到子流程第一個任務節點的連線
491                         if("default".equalsIgnoreCase(rule.getRuleType())){
492                             process.addFlowElement(genarateSequenceFlow("flow-" + (i + 1)  + (j + 1),rule.getRuleName(),
493                                     previousFlowElement.getId(),taskId,"",process));
494                             conditionExclusiveGateway.setDefaultFlow("flow-" + (i + 1)  + (j + 1));
495                         }else if("condition".equalsIgnoreCase(rule.getRuleType())){
496                             process.addFlowElement(genarateSequenceFlow("flow-" + (i + 1)  + (j + 1),rule.getRuleName(),
497                                     previousFlowElement.getId(),taskId,rule.getNumrangeitem().getExpression(),process));
498                         }
499 
500                     }/*else if(j == 0){
501                         //流程開始節點到第一個任務節點的連線
502                         process.addFlowElement(genarateSequenceFlow("flow-" + (i + 1)  + (j + 1),"開始",
503                                 previousFlowElement.getId(),taskId,"",process));
504                     }*/else if(j > 0){
505                         //上一個任務節點分支網關審核通過到當前任務節點連線
506                         sequenceFlow = genarateSequenceFlow("flow2-" +(i + 1)  + (j + 1),"通過",
507                                 previousFlowElement.getId(),taskId,examinationPass,process);
508                         process.addFlowElement(sequenceFlow);
509                         ((ExclusiveGateway)previousFlowElement).getOutgoingFlows().add(sequenceFlow);
510                     }
511 
512                     //當前分支網關審核不通過到異常結束節點連線
513                     sequenceFlow = genarateSequenceFlow("flow3-" + (i + 1)  + (j + 1),"不通過",
514                             switchGateway.getId(),abnormalEndEvent.getId(),examinationNotPass,process);
515                     process.addFlowElement(sequenceFlow);
516                     switchGateway.getOutgoingFlows().add(sequenceFlow);
517 
518                     previousFlowElement = switchGateway;
519                 }
520 
521                 //補充最后一個節點審核通過的分支連線
522                 sequenceFlow = genarateSequenceFlow("flow2-" + (i + 1)  + (taskNodes.size() + 1),"通過",
523                         previousFlowElement.getId(),endEvent.getId(),examinationPass,process);
524                 process.addFlowElement(sequenceFlow);
525                 ((ExclusiveGateway)previousFlowElement).getOutgoingFlows().add(sequenceFlow);
526             }
527         }
528         return process;
529     }
530 
531     /**
532      * Description:節點間連線
533      * Param:
534      * Return:
535      * Auther: cymiao
536      * Date: 2019/9/19 13:53
537      */
538     protected SequenceFlow genarateSequenceFlow(String id, String name,String sourceRef, String tartgetRef, String conditionExpression, Process process) {
539         SequenceFlow sequenceFlow = new SequenceFlow(sourceRef,tartgetRef);
540         sequenceFlow.setId(id);
541         if(name != null && name != ""){
542             sequenceFlow.setName(name);
543         }
544         sequenceFlow.setSourceFlowElement(process.getFlowElement(sourceRef));
545         sequenceFlow.setTargetFlowElement(process.getFlowElement(tartgetRef));
546         if(conditionExpression !=null && conditionExpression != ""){
547             sequenceFlow.setConditionExpression(conditionExpression);
548         }
549         return sequenceFlow;
550     }
551 
552     /**
553      * Description:創建任務節點
554      * Param:
555      * Return:
556      * Auther: cymiao
557      * Date: 2019/9/19 13:54
558      */
559     protected UserTask createUserTask(String name,String id,String taskType,String taskTitle){
560         UserTask task = new UserTask();
561         task.setName(name);
562         task.setId(id);
563         List<String> candidate = new ArrayList<>();
564         candidate.add(taskTitle);
565         if("role".equals(taskType)){
566             task.setCandidateGroups(candidate);
567         }else if("people".equals(taskType)){
568             task.setCandidateUsers(candidate);
569         }
570         return task;
571     }
572 
573     /**
574      * Description:創建條件網關
575      * Param:
576      * Return:
577      * Auther: cymiao
578      * Date: 2019/9/18 19:22
579      */
580     protected ExclusiveGateway createExclusiveGateway(String name,String id){
581         ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
582         exclusiveGateway.setName(name);
583         exclusiveGateway.setId(id);
584         return exclusiveGateway;
585     }
586 
587     /**
588      * Description:工作流開始事件
589      * Param:
590      * Return:
591      * Auther: cymiao
592      * Date: 2019/9/18 18:29
593      */
594     protected StartEvent createStartEvent(){
595         StartEvent startEvent = new StartEvent();
596         startEvent.setName("開始");
597         startEvent.setId("start");
598         return startEvent;
599     }
600 
601     /**
602      * Description:工作流結束事件
603      * Param:
604      * Return:
605      * Auther: cymiao
606      * Date: 2019/9/18 18:30
607      */
608     protected EndEvent createEndEvent(String id,String name,boolean hasError){
609         EndEvent endEvent = new EndEvent();
610         endEvent.setName(name);
611         endEvent.setId(id);
612         if(!hasError){
613 
614         }
615         return  endEvent;
616     }
617 }
View Code

7)ActivitiExtendOption 審核流流程操作類拓展類

  1 @Component
  2 @Primary
  3 public class ActivitiExtendOption extends ActivitiOption{
  4 
  5     @Override
  6     protected Process createProcess(ProcessEntity processInfo) {
  7         Process process = new Process();
  8 
  9         //ID:org + 組織機構ID + 流程類型
 10         process.setId("org" + processInfo.getOrgId() + processInfo.getProcessType());
 11 
 12         //NAME:組織機構名稱 + 流程類型名稱
 13         process.setName(processInfo.getOrgName() + processInfo.getProcessTypeName());
 14 
 15         //添加開始事件
 16         FlowElement startEvent = createStartEvent();
 17         process.addFlowElement(startEvent);
 18 
 19         //創建異常結束事件
 20         FlowElement abnormalEndEvent = createEndEvent("abnormalEnd","異常結束",true);
 21         process.addFlowElement(abnormalEndEvent);
 22 
 23         //添加結束事件
 24         FlowElement endEvent = createEndEvent("end","結束",false);
 25         process.addFlowElement(endEvent);
 26 
 27         List<RuleEntity> rules = processInfo.getRules();
 28         if(null == rules || rules.isEmpty()){
 29             throw new BusinessBaseException(new BusinessExceptionDesc("", BusinessExceptionDesc.SHOW_TYPE.ERROR,"審核流程不能空"));
 30         }else{
 31             List<TaskNodeEntity> taskNodes = null;
 32             //審核通過和不通過判斷表達式
 33             String examinationPass = "${examinationStatus == 'pass'}";
 34             String examinationNotPass = "${examinationStatus == 'fail'}";
 35 
 36             //創建條件網關
 37             ExclusiveGateway conditionExclusiveGateway = null;
 38             process.addFlowElement(conditionExclusiveGateway = createExclusiveGateway("條件判斷網關","condition-gateway"));
 39 
 40             //創建連線:流程開始節點到條件網關的連線
 41             SequenceFlow sequenceFlow = genarateSequenceFlow("flow-sc","網關",startEvent.getId(),conditionExclusiveGateway.getId(),"",process);
 42             process.addFlowElement(sequenceFlow);
 43 
 44             for (int i = 0; i < rules.size(); i++){
 45                 RuleEntity rule = rules.get(i);
 46 
 47                 //創建子流程
 48                 taskNodes = rule.getTaskNodes();
 49 
 50                 //規則重排序
 51                 Collections.sort(taskNodes, new Comparator<TaskNodeEntity>() {
 52                     @Override
 53                     public int compare(TaskNodeEntity o1, TaskNodeEntity o2) {
 54                         if(o1.getOrder() > o2.getOrder()){
 55                             return 1;
 56                         }else{
 57                             return -1;
 58                         }
 59                     }
 60                 });
 61 
 62                 //創建子流程節點選擇網關
 63                 ExclusiveGateway childProcessGatway = createExclusiveGateway("子流程節點選擇網關" + rule.getRuleName(),"child-process-gateway" + (i + 1));
 64                 process.addFlowElement(childProcessGatway);
 65 
 66                 //創建連線:條件網關到子流程節點選擇網關的連線
 67                 String conditionExpression = "";
 68                 if("default".equalsIgnoreCase(rule.getRuleType())){
 69                     conditionExclusiveGateway.setDefaultFlow("flow-cp" + i);
 70                 }else if("condition".equalsIgnoreCase(rule.getRuleType())){
 71                     conditionExpression = rule.getNumrangeitem().getExpression();
 72                 }
 73                 sequenceFlow = genarateSequenceFlow("flow-cp" + i,rule.getRuleName(),
 74                         conditionExclusiveGateway.getId(),childProcessGatway.getId(),conditionExpression,process);
 75                 process.addFlowElement(sequenceFlow);
 76                 conditionExclusiveGateway.getOutgoingFlows().add(sequenceFlow);
 77 
 78                 UserTask userTask = null;
 79                 TaskNodeEntity previousTaskNodeEntity = null;
 80                 ExclusiveGateway previousExclusiveGateway =  null;
 81                 for (int j = 0; j < taskNodes.size(); j++){
 82                     TaskNodeEntity taskNode = taskNodes.get(j);
 83 
 84                     String taskId = taskNode.getNodeType() + taskNode.getNodeTitle() + "-" + rule.getRuleType() + i;
 85 
 86                     //創建任務
 87                     userTask = createUserTask(taskNode.getNodeTitleName(),taskId,taskNode.getNodeType(),taskNode.getNodeTitle());
 88                     process.addFlowElement(userTask);
 89 
 90                     //創建通過和不通過結果分支網關
 91                     ExclusiveGateway switchGateway = createExclusiveGateway("結果分支網關","switchGateway" + (i + 1)  + (j + 1));
 92                     process.addFlowElement(switchGateway);
 93 
 94                     //創建當前節點到結果分支網關的連線
 95                     process.addFlowElement(genarateSequenceFlow("flow-sw" + (i + 1)  + (j + 1),"到達分支",taskId,switchGateway.getId(),"",process));
 96 
 97                     /**
 98                      * 創建連線:節點選擇網關到當前任務節點的連線
 99                      */
100                     conditionExpression = "";
101                     if(previousTaskNodeEntity != null){
102                         StringBuffer expression = new StringBuffer();
103                         expression.append("${");
104                         if(previousTaskNodeEntity.getNodeType().equals("role")){
105                             expression.append("roleCode.contains('"+ previousTaskNodeEntity.getNodeTitle() +"##')");
106                             //expression.append("roleCode == '"+ previousTaskNodeEntity.getNodeTitle() +"'");
107                         }else if(previousTaskNodeEntity.getNodeType().equals("people")){
108                             expression.append("userCode == '"+ previousTaskNodeEntity.getNodeTitle() +"'");
109                         }
110 
111                         //審核流最后一個節點的所有人發起申請時,自己審核
112                         if(j ==  taskNodes.size() -1){
113                             if(taskNode.getNodeType().equals("role")){
114                                 expression.append(" || roleCode.contains( '"+ taskNode.getNodeTitle() +"##')");
115                             }else if(taskNode.getNodeType().equals("people")){
116                                 expression.append(" || userCode == '"+ taskNode.getNodeTitle() +"'");
117                             }
118                         }
119                         expression.append("}");
120                         conditionExpression = expression.toString();
121                     }
122                     sequenceFlow = genarateSequenceFlow("flow-pt" + (i + 1)  + (j + 1),"節點選擇網關到節點",childProcessGatway.getId(),taskId,conditionExpression,process);
123                     process.addFlowElement(sequenceFlow);
124                     childProcessGatway.getOutgoingFlows().add(sequenceFlow);
125 
126                     //創建連線:上一個節點到當前節點的連線
127                     if(j == 0){
128                         //節點選擇網關到第一個任務節點連線,設置為默認選擇
129                         childProcessGatway.setDefaultFlow("flow-pt" + (i + 1)  + (j + 1));
130                     }else if(j > 0){
131                         //上一個任務節點結果分支網關審核通過到當前任務節點連線
132                         sequenceFlow = genarateSequenceFlow("flow-swy" +(i + 1)  + (j + 1),"通過",
133                                 previousExclusiveGateway.getId(),taskId,examinationPass,process);
134                         process.addFlowElement(sequenceFlow);
135                         ((ExclusiveGateway)previousExclusiveGateway).getOutgoingFlows().add(sequenceFlow);
136                     }
137 
138                     //當前分支網關審核不通過到異常結束節點連線
139                     sequenceFlow = genarateSequenceFlow("flow-swn" + (i + 1)  + (j + 1),"不通過",
140                             switchGateway.getId(),abnormalEndEvent.getId(),examinationNotPass,process);
141                     process.addFlowElement(sequenceFlow);
142                     switchGateway.getOutgoingFlows().add(sequenceFlow);
143 
144                     //當前結果分支網關設置為上一個結果選擇網關
145                     previousExclusiveGateway = switchGateway;
146 
147                     //當前任務節點設置為上一個任務節點
148                     previousTaskNodeEntity = taskNode;
149                 }
150 
151 
152                 //補充最后一個節點審核通過的分支連線
153                 sequenceFlow = genarateSequenceFlow("flow-swy" + (i + 1)  + (taskNodes.size() + 1),"通過",
154                         previousExclusiveGateway.getId(),endEvent.getId(),examinationPass,process);
155                 process.addFlowElement(sequenceFlow);
156                 ((ExclusiveGateway)previousExclusiveGateway).getOutgoingFlows().add(sequenceFlow);
157             }
158         }
159         return process;
160     }
161 
162     @Override
163     protected void sequenceFlowBackwardAnalysis(FlowElement flowElement, RuleEntity rule, int order) {
164         if(null != flowElement && flowElement instanceof ExclusiveGateway){
165             ExclusiveGateway switchGateway = (ExclusiveGateway)flowElement;
166             List<SequenceFlow> flows = switchGateway.getOutgoingFlows();
167             for (SequenceFlow flow : flows){
168                 //下一個任務節點
169                 if(flow.getTargetFlowElement() instanceof UserTask){
170                     sequenceFlowBackwardAnalysis(flow.getTargetFlowElement(),rule, ++order);
171                 }
172             }
173         }else if(flowElement instanceof UserTask){
174             UserTask userTask = (UserTask) flowElement;
175             String taskId = userTask.getId();
176             if(taskId.lastIndexOf("-") > 0){
177                 String suffiz = taskId.substring(taskId.lastIndexOf("-"));
178                 taskId = taskId.replace(suffiz,"");
179             }
180 
181             //節點類型
182             String nodeType = taskId.contains("people") ? "people" : "role";
183 
184             //節點標題
185             String nodeTitle = taskId.replace(nodeType,"");
186 
187             //節點實例
188             TaskNodeEntity nodeEntity = new TaskNodeEntity(nodeType,userTask.getName(),nodeTitle,order);
189             if(!rule.getTaskNodes().contains(nodeEntity)){
190                 rule.getTaskNodes().add(nodeEntity);
191             }
192 
193             //下一個節點對象
194             FlowElement nextFlowElement1 = userTask
195                     .getOutgoingFlows()
196                     .get(0)
197                     .getTargetFlowElement();
198             sequenceFlowBackwardAnalysis(nextFlowElement1,rule, ++order);
199         }
200         //下一個節點是結束事件節點
201         else if(null != flowElement && flowElement instanceof EndEvent){
202             return;
203         }
204     }
205 }
206 public abstract class BaseBusinessActivitiOption<T extends ApplyDomain> {
207 
208     @Autowired
209     protected ActivitiOption activitiOption;
210 
211     /**
212      * Description:創建一個申請
213      * Param:
214      * Return:
215      * Auther: cymiao
216      * Date: 2019/9/20 16:36
217      */
218     public String createApply(T applyInfo, Map<String, Object> variables) {
219         String userOrgId = getCurrentUserOrgId(applyInfo);
220         if(CommonUtils.TextUtil.isEmpty(userOrgId)){
221             throw new BusinessBaseException(new BusinessExceptionDesc("", BusinessExceptionDesc.SHOW_TYPE.ERROR,"你所屬的部門和公司沒有配置審核流,請聯系管理員!"));
222         }
223 
224         //保存申請信息
225         String businessId = saveApplyInfo(applyInfo);
226 
227         //開啟一個審核流程
228         return activitiOption.startProcessInstance(userOrgId, getCurrentApplyType(), businessId, variables);
229     }
230 
231     /**
232      * Description:保存申請信息
233      * Param:
234      * Return:
235      * Auther: cymiao
236      * Date: 2019/9/20 16:37
237      */
238     protected abstract String saveApplyInfo(T applyInfo);
239 
240     /**
241      * Description:獲取用戶可使用的流程所屬的組織結構id
242      * Param:
243      * Return:
244      * Auther: cymiao
245      * Date: 2019/9/20 16:37
246      */
247     protected abstract String getCurrentUserOrgId(T applyInfo);
248 
249     /**
250      * Description:獲取用戶的申請類型
251      * Param:
252      * Return:
253      * Auther: cymiao
254      * Date: 2019/9/20 16:37
255      */
256     protected abstract String getCurrentApplyType();
257 
258     protected abstract String getCurrentApplyTypeName();
259 
260     /**
261      * Description:查詢用戶的待處理審核信息
262      * Param:
263      * Return:
264      * Auther: cymiao
265      * Date: 2019/9/20 16:36
266      */
267     public List<T> findUserTask(String userCode, String... userRoleCode) {
268         List<T> resultApply = new ArrayList<>();
269 
270         //擁有當前審核類型的組織結構
271         List<String> userOrgIds = getCurrentUserOrgIds(userCode,getCurrentApplyType());
272 
273         //當前用戶需要審批的任務
274         List<Task> tasks = new ArrayList<>();
275         for(String orgId : userOrgIds) {
276             tasks.addAll(activitiOption.findUserTasks(
277                     activitiOption.getProcessKey(orgId, getCurrentApplyType()),
278                     userCode));
279 
280         }
281         if(null != tasks && !tasks.isEmpty()){
282             T applyInfo = null;
283             for (Task task : tasks) {
284                 String businessKey = activitiOption.findBusinesskeyByProcessInstanceId(task.getProcessInstanceId());
285                 applyInfo = findApplyInfoByBusinessId(getBusinessId(businessKey));
286                 if(null != applyInfo){
287                     applyInfo.setTaskId(task.getId());
288                     resultApply.add(applyInfo);
289                 }
290             }
291         }
292 
293         //獲取當前用戶督導的項目
294         List<T> supervisionInfo = findSupervisorApplyInfo(userCode);
295         if(null != supervisionInfo && !supervisionInfo.isEmpty()){
296             tasks = new ArrayList<>();
297             tasks.addAll(activitiOption
298                     .findRoleTasks(
299                             "supervision",
300                             0,
301                             activitiOption.findRoleTasksCount("supervision")));
302 
303             filterApplyInfo(tasks,supervisionInfo,resultApply);
304         }
305 
306         //查詢當前用戶子用戶的申請記錄
307         List<T> applyInfos = findUserApplyInfo(userCode);
308 
309         if(null != applyInfos && !applyInfos.isEmpty()){
310             tasks = new ArrayList<>();
311             for(String orgId : userOrgIds){
312                 if(userRoleCode != null && userRoleCode.length > 0){
313                     //當前用戶擁有的角色需要審批的任務
314                     for (String roleCode : userRoleCode) {
315                         tasks.addAll(activitiOption.findRoleTasks(
316 
317                                 activitiOption.getProcessKey(orgId, getCurrentApplyType()),
318                                 roleCode));
319                     }
320                 }
321             }
322 
323             filterApplyInfo(tasks,applyInfos,resultApply);
324         }
325         return resultApply;
326     }
327 
328     protected abstract T findApplyInfoByBusinessId(String businessId);
329 
330     private void filterApplyInfo(List<Task> tasks,List<T> applyInfos,List<T> resultApply){
331         if (null != tasks && !tasks.isEmpty()) {
332             String businessKey = null;
333             for (Task task : tasks) {
334                 businessKey = activitiOption.findBusinesskeyByProcessInstanceId(task.getProcessInstanceId());
335                 int currentIndex = -1;
336                 for (T t : applyInfos) {
337                     if (businessKey.equals(getBusinessKey(t))) {
338                         t.setTaskId(task.getId());
339                         resultApply.add(t);
340                         currentIndex++;
341                         break;
342                     }
343                 }
344                 if (currentIndex > -1) {
345                     applyInfos.remove(currentIndex);
346                 }
347             }
348         }
349     }
350 
351     /**
352      * Description:獲取當前用戶督導的項目信息
353      * Param:
354      * Return:
355      * Auther: cymiao
356      * Date: 2019/10/16 19:48
357      */
358     protected abstract List<T> findSupervisorApplyInfo(String userCode);
359 
360     /**
361      * Description:當前用戶可見的擁有當前類型流程的組織機構
362      * Param:
363      * Return: 
364      * Auther: cymiao
365      * Date: 2019/9/25 16:07
366      */
367     protected abstract List<String> getCurrentUserOrgIds(String userCode,String processType);
368 
369     /**
370      * Description:申請記錄的businessKey
371      * Param:
372      * Return:
373      * Auther: cymiao
374      * Date: 2019/9/20 16:34
375      */
376     private String getBusinessKey(T t) {
377         Field[] fields = t.getClass().getDeclaredFields();
378         TableId id;
379         for (Field field : fields) {
380             id = field.getAnnotation(TableId.class);
381             if (id != null) {
382                 try {
383                     field.setAccessible(true);
384                     Object o = field.get(t);
385                     return getCurrentApplyType() + "-" + String.valueOf(o);
386                 } catch (IllegalAccessException e) {
387                     e.printStackTrace();
388                 }
389             }
390         }
391 
392         return null;
393     }
394 
395     private String getBusinessId(String businessKey){
396         return businessKey.replaceAll(getCurrentApplyType() + "-","");
397     }
398 
399     /**
400      * Description:用戶未完成審核的申請記錄
401      * Param:
402      * Return:
403      * Auther: cymiao
404      * Date: 2019/9/20 16:35
405      */
406     protected abstract List<T> findUserApplyInfo(String userCode);
407 
408     /**
409      * Description:發布工作流
410      * Param:
411      * Return:
412      * Auther: cymiao
413      * Date: 2019/9/21 9:58
414      */
415     public void deploymentProcess(JSONArray propertiyJson) {
416         ProcessEntity processInfo = processPropertyDeal(propertiyJson);
417         activitiOption.deployDeployment(processInfo);
418     }
419 
420     /**
421      * Description:發布工作流
422      * Param:
423      * Return:
424      * Auther: cymiao
425      * Date: 2019/9/27 15:06
426      */
427     public void deploymentProcess(ProcessEntity processInfo){
428         activitiOption.deployDeployment(processInfo);
429     }
430 
431     /**
432      * Description:工作流屬性處理
433      * Param:
434      * Return:
435      * Auther: cymiao
436      * Date: 2019/9/21 9:58
437      */
438     private ProcessEntity processPropertyDeal(JSONArray propertiyJson){
439         return null;
440     }
441 
442     /**
443      * Description:處理申請任務
444      * Param:
445      * Return: 
446      * Auther: cymiao
447      * Date: 2019/9/21 16:46
448      */
449     public String dealApply(String taskId,String examineUser, Map<String,Object> variables){
450         String processInstanceId = activitiOption.findProcessInstanceIdByTaskId(taskId);
451         String businesskey = activitiOption.findBusinesskeyByProcessInstanceId(processInstanceId);
452         activitiOption.taskComplete(taskId,examineUser,variables);
453 
454         String businessId = getBusinessId(businesskey);
455 
456         //審核不通過
457         if("fail".equals(String.valueOf(variables.get("examinationStatus")))){
458             updateBusinessApplyData(businessId,false);
459         }else{
460             //獲取歷史
461             List<HistoricActivityInstance> his = activitiOption.findProcessHistoryByStartTime(processInstanceId);
462             if (null != his && !his.isEmpty()){
463                 if("end".equals(his.get(his.size() - 1).getActivityId())){
464                     updateBusinessApplyData(businessId,true);
465                 }
466             }
467         }
468 
469         return businessId;
470     }
471 
472     /**
473      * Description:更新申請記錄和業務數據
474      * Param:
475      * Return: 
476      * Auther: cymiao
477      * Date: 2019/9/21 17:41
478      */
479     protected abstract void updateBusinessApplyData(String businessId,boolean examinationStatus);
480 
481     /**
482      * Description:獲取流程定義
483      * Param:
484      * Return:
485      * Auther: cymiao
486      * Date: 2019/9/26 17:54
487      */
488     public ProcessEntity findProcess(String orgId){
489         return activitiOption.findProcess(orgId, getCurrentApplyType(),getCurrentApplyTypeName());
490     }
491 
492 }
View Code

8)ActivitiConfig 審核流相關類配置信息

 1 @Configuration
 2 public class ActivitiConfig {
 3 
 4     @Autowired
 5     @Qualifier("dynamicDataSource")
 6     private DynamicDataSource dynamicDataSource;
 7 
 8     @Bean
 9     public ActivitiEndEventListener endEventListener(){
10         return new ActivitiEndEventListener();
11     }
12 
13     @Bean
14     public ProcessEngine processEngine(@Autowired ActivitiEndEventListener endEventListener){
15         StandaloneProcessEngineConfiguration configuration = (StandaloneProcessEngineConfiguration) ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
16         configuration.setDataSource(dynamicDataSource);
17         configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
18 
19         //添加監聽
20         List<ActivitiEventListener> listeners = new ArrayList<>();
21         listeners.add(endEventListener);
22         configuration.setEventListeners(listeners);
23 
24         return configuration.buildProcessEngine();
25     }
26 
27     @Bean
28     public RepositoryService repositoryService(@Autowired ProcessEngine processEngine){
29         return processEngine.getRepositoryService();
30     }
31 
32     @Bean
33     public RuntimeService runtimeService(@Autowired ProcessEngine processEngine,@Autowired ActivitiEndEventListener endEventListener){
34         RuntimeService runtimeService = processEngine.getRuntimeService();
35         endEventListener.setRuntimeService(runtimeService);
36         return runtimeService;
37     }
38 
39     @Bean
40     public TaskService taskService(@Autowired ProcessEngine processEngine,@Autowired ActivitiEndEventListener endEventListener){
41         TaskService taskService = processEngine.getTaskService();
42         endEventListener.setTaskService(taskService);
43         return taskService;
44     }
45 
46     @Bean
47     public HistoryService historyService(@Autowired ProcessEngine processEngine,@Autowired ActivitiEndEventListener endEventListener){
48         HistoryService historyService = processEngine.getHistoryService();
49         endEventListener.setHistoryService(historyService);
50         return historyService;
51     }
52 }
View Code

4、使用總結

  activiti的使用靈活多變,activiti自身有提供配置審核流的界面,經常很難融合與我們自己的產品設計中,所以需要我們按照自己的需求進行二次實現,

  當然首當其沖需要解決的問題就是,界面的配置信息應放在怎樣的一個載體中,再次就是如何有效的表達審核流的信息使能夠生產一個滿足業務需求的審核流;

  最后就是這些載體信息如何轉化為activiti需要的BPMN文件,並且如何反向解析回顯配置。

  以上這些問題是實現二次開發的最基礎也是最重要需要考慮和解決的問題,至於其他的細節就需要在實現的過程中逐步去克服和處理了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM