Activiti动态设置办理人扩展

Posted bootdo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activiti动态设置办理人扩展相关的知识,希望对你有一定的参考价值。

关键词:Assignee、Candidate users、Candidate groups;setAssignee、taskCandidateUser、taskCandidateGroup

主要解决问题:Activiti动态给任务节点设置办理人。

情景:

我们在做工作流开发,学习的时候一般都有这么一个过程:

第一阶段:最开始学习的时候,喜欢在设计流程的时候写死人名(即)办理人,这个阶段是入门级。而且你也会觉得这样做非常 so easy(方便、简单)。可是慢慢的,你就会发现,每次需要换人,你就要重新设计流程实例(workflow processInstance),一系列的design->Deployment->start processInstance,从此你再也不觉得so easy 了。

第二阶段:于是你开始使用了EL表达式变量,这个阶段代表你已经到了提升阶段。可以使用委托类来设置办理人了,是动态的设置哦。但是,你并没有整合自己的权限系统,用的还是Activiti官方的user表和group表,慢慢的,你发现一旦自己的权限系统角色和用户做了调整,那么自己还得去维护这几个表。

第三阶段:于是,你开始整合自己的权限系统,这个阶段基本是熟练了,可以说是已经完美了。但是这个阶段,每次发送的时候,我们还需要选择一个人去办理他,但是个人觉得,要达到完美状态是不可能的,但是我们还可以自己去做扩展使得它更加的好用,达到我们逾期的目的,(个人观点)。

第四阶段:其实很多人都会去扩展功能的,源码改造,或者模块扩展。在流程部署的时候就设置好办理人,这样,每次发送的时候,我们并不需要去选择办理人。

设置办理人色几种方案

我们先回顾一下,比较传统的动态设置任务办理人的几种方法:

第一种:在流程设置死,这个感觉无需多说,就是在设计流程的时候,在Assignee里面填写我们的办理人姓名或者相关的ID即可。

技术图片

 

第二种:通过委托类(监听类)设置。在流程设计的时候设置监听类,并且在办理人里面设置EL表达式 ${UserId}(随便自己命名)。然后每次办理的时候选择一个办理人。然后传递一个变量过去,然后下一个环节的监听类会设置办理人。

 

1   Map<String,Object> map = delegateTask.getVariables();
2 
3 delegateTask.setAssignee(map.get("UserId").toString());

 

 

 

设置办理人可能有三种方案,

设置办理人的三种方案是有优先级的。

设置办理人优先级:

Assignee>Candidate users>Candidate groups。

设置办理人色几种模式

第一种:指定办理人模式,即设置办理人,就是设置Assignee。Assignee 受让人; 受托人,代理人; 被指定人;办理人只能指定一个人,不能使用逗号分隔。默认执行签收操作taskService.claim(taskId, currentUserId);在ACT_HI_TASKINST和ACT_RU_TASK会产生数据,这两个表里面的Assignee_字段就是设置的办理人姓名或者对象的ID

第二种:设置候选用户,候选用户设置办理人不是很多的情况下使用,而且需要签收,也就是说我们常说的抢件模式,Candidate users  候选用户,设置候选组的前提是没有指定Assignee,(即没有执行签收操作)。设置候选组需要主动签taskService.claim(taskId, currentUserId);

 

 

第三种:这只候选组,这个就是这只办理角色或者办理岗位,适合使用在办理人比较多的情况下,而且涉及到几个部门的情形。Candidate groups  候选组

候选组与候选用户类似,只是要获取候选用户,需要根据候选组找到对应的用户。

 

涉及API:

 

1 taskService.createTaskQuery().taskAssignee(param);

根据用户来查询任务(待办任务)

 

1 taskService.createTaskQuery().taskCandidateUser(param);  

根据候选用户查询任务(待签收任务)

 

1 taskService.createTaskQuery().taskCandidateGroup(param);

候选组查询任务(待签收任务)

 

1 TaskService().setAssignee(taskId,userId);

设置办理人 

 

1 taskService().addCandidateGroup(taskId, groupid);

这只候选组,可以添加多个,每次一个addCandidateGroup添加一个

 

1 taskService().addCandidateUser(taskId,userid);

这只候选用户,可以添加多个,每次一个addCandidateUser添加一个

 

1 taskService.claim(taskId, currentUserId);

签收操作。

 

扩展实现

扩展需要添加中间表,我们使用TDD(驱动开发模式)来实现。

需呀增加一个中间表。

流程办理人表(act_comm_taskassignee)

字段

名称

是否为空

备注

ID

主键ID

M

 

SID

节点ID

M

 

assignee

办理人

O

 

rolegroup

候选组

O

 

assigneeType

办理人类型

M

1办理人,2为候选人,3为候选组

activitiname

节点名称

O

 

 

建表SQL:

技术图片
 1 CREATE TABLE `act_comm_taskassignee` (
 2 
 3   `Id` int(11) NOT NULL AUTO_INCREMENT,
 4 
 5   `Sid` varchar(45) NOT NULL,
 6 
 7   `assignee` varchar(45) DEFAULT NULL,
 8 
 9   `rolegroup` varchar(45) DEFAULT NULL,
10 
11   `assigneeType` varchar(45) DEFAULT NULL,
12 
13   `assigneename` varchar(200) DEFAULT NULL,
14 
15   `activitiname` varchar(255) DEFAULT NULL,
16 
17   PRIMARY KEY (`Id`),
18 
19   UNIQUE KEY `Id_UNIQUE` (`Id`)
20 
21 ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
技术图片

 

实体Model:

 

技术图片
  1 /**
  2 
  3  *
  4 
  5  */
  6 
  7 package light.mvc.model.workflow;
  8 
  9  
 10 
 11 import javax.persistence.Entity;
 12 
 13 import javax.persistence.Table;
 14 
 15  
 16 
 17 import light.mvc.model.base.IdEntity;
 18 
 19  
 20 
 21 import org.hibernate.annotations.DynamicInsert;
 22 
 23 import org.hibernate.annotations.DynamicUpdate;
 24 
 25  
 26 
 27 /** 
 28 
 29  *  
 30 
 31  * 项目名称:lightmvc 
 32 
 33  * 类名称:FlowAssignee 
 34 
 35  * 类描述: 
 36 
 37  * 创建人:邓家海 
 38 
 39  * 创建时间:2017年8月15日 下午10:01:46 
 40 
 41  * 修改人:deng 
 42 
 43  * 修改时间:2017年8月15日 下午10:01:46 
 44 
 45  * 修改备注: 
 46 
 47  * @version  
 48 
 49  *  
 50 
 51  */
 52 
 53 @Entity
 54 
 55 @Table(name="act_comm_taskassignee")
 56 
 57 @DynamicInsert(true)
 58 
 59 @DynamicUpdate(true)
 60 
 61 public class FlowAssignee extends IdEntity implements java.io.Serializable {
 62 
 63       private String sid;
 64 
 65       /**
 66 
 67        * @return the activitiname
 68 
 69        */
 70 
 71       public String getActivitiname() {
 72 
 73            return activitiname;
 74 
 75       }
 76 
 77  
 78 
 79       /**
 80 
 81        * @param activitiname the activitiname to set
 82 
 83        */
 84 
 85       public void setActivitiname(String activitiname) {
 86 
 87            this.activitiname = activitiname;
 88 
 89       }
 90 
 91  
 92 
 93       private String assignee;
 94 
 95       private String rolegroup;
 96 
 97       private String activitiname;
 98 
 99       private Integer assigneetype;
100 
101      
102 
103       public FlowAssignee(){
104 
105            super();
106 
107       }
108 
109      
110 
111       public FlowAssignee(String sid,String assignee,String rolegroup,Integer assigneetype,String activitiname){
112 
113            super();
114 
115            this.assignee=assignee;
116 
117            this.sid=sid;
118 
119            this.rolegroup=rolegroup;
120 
121            this.assigneetype=assigneetype;
122 
123            this.activitiname=activitiname;
124 
125       }
126 
127  
128 
129       /**
130 
131        * @return the sid
132 
133        */
134 
135       public String getSid() {
136 
137            return sid;
138 
139       }
140 
141  
142 
143       /**
144 
145        * @param sid the sid to set
146 
147        */
148 
149       public void setSid(String sid) {
150 
151            this.sid = sid;
152 
153       }
154 
155  
156 
157       /**
158 
159        * @return the assignee
160 
161        */
162 
163       public String getAssignee() {
164 
165            return assignee;
166 
167       }
168 
169  
170 
171       /**
172 
173        * @param assignee the assignee to set
174 
175        */
176 
177       public void setAssignee(String assignee) {
178 
179            this.assignee = assignee;
180 
181       }
182 
183  
184 
185       /**
186 
187        * @return the rolegroup
188 
189        */
190 
191       public String getRolegroup() {
192 
193            return rolegroup;
194 
195       }
196 
197  
198 
199       /**
200 
201        * @param rolegroup the rolegroup to set
202 
203        */
204 
205       public void setRolegroup(String rolegroup) {
206 
207            this.rolegroup = rolegroup;
208 
209       }
210 
211  
212 
213       /**
214 
215        * @return the assigneetype
216 
217        */
218 
219       public Integer getAssigneetype() {
220 
221            return assigneetype;
222 
223       }
224 
225  
226 
227       /**
228 
229        * @param assigneetype the assigneetype to set
230 
231        */
232 
233       public void setAssigneetype(Integer assigneetype) {
234 
235            this.assigneetype = assigneetype;
236 
237       }
238 
239      
240 
241 }
技术图片

 

 

核心实现代码:

第一步:根据部署ID来查找所有的节点,目的(找到节点ID):

技术图片
 1 @Test
 2 
 3     public void getDeploymentActivitiIdList(){
 4 
 5         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 6 
 7        
 8 
 9         String deploymantId="57577";
10 
11                
12 
13         ProcessDefinition processDefinition=processEngine.getRepositoryService().createProcessDefinitionQuery().deploymentId(deploymantId).singleResult();
14 
15        
16 
17         ProcessDefinitionEntity processDefinitionEntity=(ProcessDefinitionEntity)((RepositoryServiceImpl) processEngine
18 
19                 .getRepositoryService()).getDeployedProcessDefinition(processDefinition.getId());
20 
21        
22 
23         List<ActivityImpl> activityList=processDefinitionEntity.getActivities();
24 
25        
26 
27         for(ActivityImpl activiti:activityList) {
28 
29             System.out.println("节点ID:"+activiti.getId());
30 
31  
32 
33             System.out.println("节点名称:"+activiti.getProperty("name"));
34 
35         }
36 
37     }
技术图片

 

 

 技术图片

 

 

 

第二步,设置办理人,或者候选组,用户:

 

技术图片
 1 /**
 2 
 3      * 1.设置办理人,一个节点一个办理人,指定办理人模式,不需要签收,办理人模式
 4 
 5      * 2。设置岗位    1)通过角色,查找权限表,签收模式,角色岗位模式
 6 
 7      *          2)通过节点——>办理人,签收模式,节点(一)-->办理人(多)  ,角色岗位模式
 8 
 9      */
10 
11     @Test
12 
13     public void setAgneeByActivitiSid(){
14 
15         Session session = sessionFactory.openSession();
16 
17         String sid="sid-AEC4023A-DEB1-44C8-8784-C3C10F6B484A";   //节点id
18 
19         String ActivitiName="总经理";     //节点名称
20 
21         FlowAssignee fa=new FlowAssignee(); 
22 
23         fa.setActivitiname(ActivitiName);  
24 
25         fa.setAssignee("张三");  //办理人
26 
27         fa.setAssigneetype(1);  //1是指定办理人,2是指定岗位
28 
29         fa.setSid(sid);
30 
31         session.save(fa);
32 
33    
34 
35        
36 
37         sid="sid-C8781FAE-02B8-4F8D-9A7D-A8AB4A8CB95A";   //节点id
38 
39          ActivitiName="经理";     //节点名称
40 
41         fa=new FlowAssignee(); 
42 
43         fa.setActivitiname(ActivitiName); 
44 
45         fa.setActivitiname(ActivitiName);
46 
47         //fa.setAssignee("李四");  //办理人  设置候选组,不能设置办理人
48 
49         fa.setRolegroup("产品部");  //办理岗位
50 
51         fa.setAssigneetype(1);  //1是指定办理人,2是指定岗位
52 
53         fa.setSid(sid);
54 
55         session.save(fa);
56 
57        
58 
59         session.flush();
60 
61     }
技术图片

 

 技术图片

 

 

 

第三步:设置启动流程,并设置第一个环节的办理人:

技术图片
 1 @Test
 2 
 3     public void SetAgnee(){
 4 
 5         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 6 
 7        
 8 
 9         String deploymantId="57577";
10 
11         String pid=processEngine.getRepositoryService().createProcessDefinitionQuery().deploymentId(deploymantId)
12 
13                 .singleResult().getId();
14 
15         ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的service
16 
17         .startProcessInstanceById(pid);//使用流程定义的KEY启动流程实例,key对应helloword。bpmn中对应的ID属性值
18 
19        
20 
21         String pdid=pi.getProcessDefinitionId();
22 
23        
24 
25         List<Task> taskList=processEngine.getTaskService().createTaskQuery().deploymentId(deploymantId).active().list();
26 
27        
28 
29         for(Task task:taskList){
30 
31              ExecutionEntity execution = (ExecutionEntity)processEngine.getRuntimeService().createExecutionQuery().executionId(task.getExecutionId())
32 
33                         .singleResult();
34 
35                 String activitiId = execution.getActivityId();
36 
37                
38 
39                 Session session = sessionFactory.openSession();
40 
41              List<FlowAssignee> list=session.createQuery("from FlowAssignee where sid=‘"+activitiId+"‘").list();
42 
43  
44 
45              if(list.size()>0)
46 
47              for(FlowAssignee fa:list){
48 
49              if(fa.getAssigneetype()==1){
50 
51                    processEngine.getTaskService().setAssignee(task.getId(), fa.getAssignee());
52 
53               }else  if(fa.getAssigneetype()==2){
54 
55                   processEngine.getTaskService().addCandidateUser(task.getId(), fa.getAssignee());
56 
57              }else if(fa.getAssigneetype()==3){
58 
59                   processEngine.getTaskService().addCandidateGroup(task.getId(), fa.getRolegroup());
60 
61              }           
62 
63        
64 
65                   
66 
67              }      
68 
69        
70 
71         }
72 
73     }
技术图片

 

 

 

到这里,我们的就已经完成了根据节点设置办理人的人:

 

查询一下:

技术图片
 1 @Test
 2 
 3     public void getMyTask(){
 4 
 5         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 6 
 7         String CandGroup="产品部";
 8 
 9         Task task=processEngine.getTaskService().createTaskQuery().taskCandidateGroup(CandGroup).active().singleResult();
10 
11         List<IdentityLink> ilList=processEngine.getTaskService().getIdentityLinksForTask(task.getId());
12 
13         System.out.println("办理人:"+task.getAssignee());
14 
15         System.out.println("任务ID:"+task.getId());
16 
17         System.out.println("任务ID:"+task.getName());
18 
19         for(IdentityLink i:ilList){
20 
21             System.out.println("组ID:"+i.getGroupId());
22 
23             System.out.println("用户:"+i.getUserId());
24 
25         }
26 
27  
28 
29     }
技术图片

 

 

技术图片

 

 

 

结果是正确的。

以上是关于Activiti动态设置办理人扩展的主要内容,如果未能解决你的问题,请参考以下文章

activiti怎么设置一下个节点的办理人??

activiti 办理人在哪个表

Activiti工作流-进阶

Activiti学习记录

activiti6+springboot2 的第三个简单demo 动态设置任务节点处理人(多人并行 无序)

activiti 怎么获取变量