因為近期在做工作流結合業務,總結一下
第一階段:最開始喜歡在設計流程的時候寫死人名(即)辦理人,這個階段是入門級。而且你也會覺得這樣做非常 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基礎有一定的功底的,如果不是很熟悉,請先使用委托類或者直接設置辦理人
本文主要實現了核心功能,整合到系統功能暫時還沒實現。但是有基礎的人看完本文就會知道怎么進行擴展





