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文件,并且如何反向解析回显配置。

  以上这些问题是实现二次开发的最基础也是最重要需要考虑和解决的问题,至于其他的细节就需要在实现的过程中逐步去克服和处理了。

posted @ 2020-04-20 16:15  时间足迹  阅读(1019)  评论(0编辑  收藏