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动态设置办理人扩展的更多相关文章
- activiti7启动流程实例,动态设置assignee人
package com.zcc.activiti03; import org.activiti.engine.ProcessEngine;import org.activiti.engine.Proc ...
- activiti 工作流 动态 设置 指定 节点任务人、责任人、组 的实现方式
首先给大家看一下我的流程图: 流程文件leaveBill.bpmn <?xml version="1.0" encoding="UTF-8"?>&l ...
- activiti 工作流动态设置指定节点任务人、责任人、组的实现方式
首先给大家看一下我的流程图: 流程文件leaveBill.bpmn <?xml version="1.0" encoding="UTF-8"?>&l ...
- activiti 任务节点 处理人设置【转】
转自http://blog.csdn.net/qq_30739519/article/details/51225067 1.1.1. 前言 分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自 ...
- activiti 任务节点 处理人设置
1.1.1. 前言 分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 我们在使用activiti 工作流引擎的时候, ...
- 你有没有觉得邮件发送人固定配置在yml文件中是不妥当的呢?SpringBoot 动态设置邮件发送人
明月当天,不知道你有没有思念的人 前言 之前其实已经写过SpringBoot异步发送邮件,但是今天在一个小项目中要用到发送邮件时,我突然觉得邮件发送人只有一个,并且固定写在yml文件中,就是非常的不妥 ...
- activiti 动态配置 activiti 监听引擎启动和初始化(高级源码篇)
1.1.1. 前言 用户故事:现在有这样一个需求,第一个需求:公司的开发环境,测试环境以及线上环境,我们使用的数据库是不一样的,我们必须能够任意的切换数据库进行测试和发布,对数据库连接字符串我们需要加 ...
- easyui表单多重验证,动态设置easyui控件
要实现的功能:在做添加学生信息的时候,利用easyui的验证功能判断 学号是否重复和学号只能为数字 最终效果如下图: 但在做这个的过程中,遇到了一系列的问题: 扩展validatebox的验证方法,最 ...
- JavaScript DOM编程基础精华03(动态设置,层的操作,性能问题)
代码是否需要放置到onload中 //如果js代码需要操作页面上的元素,则将该代码放到onload里面. //因为当页面加载完毕之后页面上才会有相关的元素 //如果js代码中没有操作 ...
随机推荐
- Shell逻辑语句
case esac 语句 参考 :https://blog.csdn.net/wu20093346/article/details/47210809 case ... esac 与其他语言中的 swi ...
- 前台返回json数据的常用方式+常用的AJAX请求后台数据方式
我个人开发常用的如下所示: 之所以像下面这样下,一是前台Ajax,二是为安卓提供接口数据 现在常用的是返回JSON数据,XML的时代一去不复返 JSON相对于XML要轻量级的多 对JSON不是十分熟悉 ...
- DNS主从复制及区域传送
前言 DNS主从复制,就是将主DNS服务器的解析库复制传送至从DNS服务器,进而从服务器就可以进行正向.反向解析了.从服务器向主服务器查询更新数据,保证数据一致性,此为区域传送.也可以说,DNS区域传 ...
- linux 服务器安全加固和内核参数调优 nf_conntrack
0.内部设置跳板机,服务器只能通过跳板机登录1.禁止ROOT用户远程登录和登录端口 禁止ROOT用户远程登录 .打开 /etc/ssh/sshd_config PermitRootLogin no . ...
- [01] MyBatis概述
传统的JDBC来做DAO层,做了下面这几件事: 加载驱动 获取连接 执行SQL语句 获取操作结果封装信息 返回操作结果 而实际上DAO层最关心的是什么呢,就是后面三点就完事,JDBC显得太繁琐: 执行 ...
- 使用Webuploader大文件分片传输
背景:50G大文件的HTTP上传至服务器. 好了,根据这个命题,可以开始研究我们怎么做才能把这么大的文件上传成功. 分片上传是肯定的,断点续传也是要有的,进度可视化那就更好了,基于这些,我选择了Web ...
- odoo11 添加自定义模块报错问题
在昨天解决了数据库管理页面布局混乱的问题之后,如何设置自己的custom_addons模块文件夹成了主要问题,建立自己的custom_addons文件夹,可以使用git命令来管理自己所写代码的版本了, ...
- CentOS安装noVNC,以Web方式交付VNC远程连接
什么是noVNC noVNC 是一个 HTML5 VNC 客户端,采用 HTML 5 WebSockets, Canvas 和 JavaScript 实现,noVNC 被普遍用在各大云计算.虚拟机控制 ...
- NFS共享文件系统部署
1. 概述 本篇博客主要是介绍如何安装和使用NFS服务. 2. 安装软件包 首先确认系统是否已经安装相应的软件包,执行命:rpm -qa | egrep "rpcbind|nfs-utils ...
- Sql_索引分析
「索引就像书的目录, 通过书的目录就准确的定位到了书籍具体的内容」,这句话描述的非常正确, 但就像脱了裤子放屁,说了跟没说一样,通过目录查找书的内容自然是要比一页一页的翻书找来的快,同样使用的索引的人 ...