關鍵詞:Assignee、Candidate users、Candidate groups;setAssignee、taskCandidateUser、taskCandidateGroupjava
主要解決問題:Activiti動態給任務節點設置辦理人。session
咱們在作工做流開發,學習的時候通常都有這麼一個過程:mvc
第一階段:最開始學習的時候,喜歡在設計流程的時候寫死人名(即)辦理人,這個階段是入門級。並且你也會以爲這樣作很是 so easy(方便、簡單)。但是慢慢的,你就會發現,每次須要換人,你就要從新設計流程實例(workflow processInstance),一系列的design->Deployment->start processInstance,今後你不再以爲so easy 了。學習
第二階段:因而你開始使用了EL表達式變量,這個階段表明你已經到了提高階段。可使用委託類來設置辦理人了,是動態的設置哦。可是,你並無整合本身的權限系統,用的仍是Activiti官方的user表和group表,慢慢的,你發現一旦本身的權限系統角色和用戶作了調整,那麼本身還得去維護這幾個表。this
第三階段:因而,你開始整合本身的權限系統,這個階段基本是熟練了,能夠說是已經完美了。可是這個階段,每次發送的時候,咱們還須要選擇一我的去辦理他,可是我的以爲,要達到完美狀態是不可能的,可是咱們還能夠本身去作擴展使得它更加的好用,達到咱們逾期的目的,(我的觀點)。spa
第四階段:其實不少人都會去擴展功能的,源碼改造,或者模塊擴展。在流程部署的時候就設置好辦理人,這樣,每次發送的時候,咱們並不須要去選擇辦理人。hibernate
咱們先回顧一下,比較傳統的動態設置任務辦理人的幾種方法:設計
第一種:在流程設置死,這個感受無需多說,就是在設計流程的時候,在Assignee裏面填寫咱們的辦理人姓名或者相關的ID便可。代理
第二種:經過委託類(監聽類)設置。在流程設計的時候設置監聽類,而且在辦理人裏面設置EL表達式 ${UserId}(隨便本身命名)。而後每次辦理的時候選擇一個辦理人。而後傳遞一個變量過去,而後下一個環節的監聽類會設置辦理人。code
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 候選組
候選組與候選用戶相似,只是要獲取候選用戶,須要根據候選組找到對應的用戶。
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 }
結果是正確的。