一、代理人
一个用户任务只允许有一个代理人。为一个任务分配代理人后act_ru_task表的ASSIGNEE_字段会被设置为响应的值。
审批任务设置assignee变量,表示是该任务的负责人:
<userTask id="sid-9253B2C0-D7CF-49C9-BE00-3B68D87413D4" name="审批" activiti:assignee="${assignee}"></userTask>
启动流程分配代理人:
// 启动流程分配代理人
Map<String,Object> map = new HashMap<>();
map.put("assignee", "zhangsan");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave", map);
查询任务指定代理人:
// 可通过代理人查询任务列表
List<Task> list = taskService.createTaskQuery().taskAssignee("zhangsan").list();
二、候选人
一个任务可以设置多个候选人,候选人在业务上指的是有权对该任务进行操作的群体。 某个候选人签收后,其他候选人就看不到该任务。
- 可以使用
activiti:candiateUsers=”用户 1,用户 2,用户 3”
的这种方式来实现设置一组候选人
直接赋值多个候选人示例:
<userTask activiti:candidateUsers="zhangsan,lisi,wangwu" activiti:exclusive="true" id="_3" name="审批"/>
动态设置候选人变量 candidateUsers:
<userTask id="sid-31845D76-A308-4442-AE19-4AA4238DB39A" name="审批" activiti:candidateUsers="${candidateUsers}"></userTask>
这里的candidateUsers是一个流程变量,以list的形式存放了候选人列表。
注意任务和候选人的关系存储在act_ru_identitylink表中
启动流程分配候选人:
// 启动流程分配候选人
List<String> candidateUsers = new ArrayList<>();
candidateUsers.add("zhangsan");
candidateUsers.add("lisi");
Map<String,Object> variableMap = new HashMap<>();
variableMap.put("candidateUsers", candidateUsers);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave", variableMap);
三、候选组
用来把一个群体的人指定为一个任务的权限人,对应的是activiti中的用户组,分配一个用户组id到某个任务上,可以指定整个组的人为该任务的候选人。 属于该候选组的用户就可以签收然后办理该任务。
如果候选组中存在多个用户,那么只有其中的某个用户签收了任务,那么其它用户就看不到该任务。 只要任务还未被签收,候选组内的任意用户都可以签收该任务;一旦任务被签收,候选组内的其他用户就无法查看与签收该任务咯。
可以使用activiti:candidateGroups=”用户组1,用户组2,用户组3”的这种方式来实现设置一组候选人
动态设置候选组变量candidateGroup:
<userTask id="juel-candidateGroup" name="审批" activiti:candidateGroups="${candidateGroup}"></userTask>
1 这里的candidateGroup也是一个流程变量,其中存放了用户组id的lsit集合。
注意任务和候选组的关系存储在act_ru_identitylink表中
启动流程分配候选组:
// 启动流程分配候选组
Map<String,Object> map = new HashMap<>();
List<String> groupList = new ArrayList<>();
groupList.add("项目经理");
groupList.add("测试");
map.put("candidateGroup",groupList);
runtimeService.startProcessInstanceByKey("leave", map);
四、组任务办理流程
办理流程:
- 指定候选人,查询该候选人当前的待办任务
- 候选人不能立即办理任务,要先拾取
- 候选人拾取,将候选人的组任务,变成个人任务,原来候选人就变成了该任务的负责人,其他候选人就看不到该任务
- 候选人完成任务
- 如果个人不想办理该组任务,可以归还组任务,归还后该用户不再是该任务的负责人
- 查询该候选人个人任务
taskService.setAssignee(taskId, null); // 设置为null,归还组任务
也可以将任务委托给其他人(委托的用户可以不是候选人)
查询该候选人个人任务
taskService.setAssignee(taskId, “其他人”);
五、UEL表达式
表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。 如下:
${order.price > 100 && order.price < 250}
UEL-value
${applyUserId}:applyUserId这个变量是 activiti 的一个流程变量
Map<String, Object> map = new HashMap<>();
map.put("applyUserId", "zhangsan");
${user.applyUserId}:表示通过调用 user 的 getter 方法获取 applyUserId 值
User user = new User();
Map<String, Object> map = new HashMap<>();
map.put("user", user);
UEL-method
${User.getApplyUserId()}:userBean 是 spring 容器中的一个 bean,调用该 bean 的 getApplyUserId()方法
UEL method结合value
${IUserService.findManagerForEmployee(emp)}:IUserService是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti流程变量, emp 作为参数传到 IUserService.findManagerForEmployee 方法中
Activiti7的Servcie核心接口
Service接口 | 说明 |
---|---|
RuntimeService | 运行时 Service,可以处理所有正在运行状态的流程实例和任务等 |
RepositoryService | 流程仓库 Service,主要用于管理流程仓库,比如流程定义的控制管理(部 署、删除、挂起、激活…) |
DynamicBpmnService | RepositoryService可以用来部署流程定义(使用xml形式定义好的),一旦 部署到Activiti(解析后保存到DB),那么流程定义就不会再变了,除了修改xml定义文件内容;而DynamicBpmnService就允许我们在程序运行过程中去修改流程定义,例如:修改流程定义中的分配角色、优先级、流程流转的条件。 |
TaskService | 任务 Service,用于管理和查询任务,例如:签收、办理等 |
HistoryService | 历史Service,可以查询所有历史数据,例如:流程实例信息、参与者信息、完成时间… |
ManagementService | 引擎管理Service,和具体业务无关,主要用于对Activiti流程引擎的管理和维护。 |
核心 Service 接口实例获取方式
// 会在首次调用时初始化并构建一个流程引擎,此后始终返回相同的流程引擎。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 引擎管理类
ManagementService managementService = processEngine.getManagementService();
// 动态修改流程管理类
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
// 流程运行管理类
RuntimeService runtimeService = processEngine.getRuntimeService();
// 流程仓库管理类
RepositoryService repositoryService = processEngine.getRepositoryService();
// 任务管理类
TaskService taskService = processEngine.getTaskService();
// 历史管理类
HistoryService historyService = processEngine.getHistoryService();
// activiti 7 没有IdentityService和FormService接口
//IdentityService identityService = processEngine.getIdentityService();
// FormService formService = processEngine.getFormService();
Activiti7 25张数据表分析
表分类 | 表名 | 说明 |
---|---|---|
通用数据 | ||
act_ge_bytearray | 二进制数据表(流程图) | |
act_ge_property | 属性数据表,存储整个流程引擎级别的数据,初始化表结构时,会插入版本号信息等 | |
历史信息 | ||
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_re_deployment | 部署信息表 | |
act_re_model | 流程设计模型表 | |
act_re_procdef | 流程定义数据表 | |
流程运行数据表 | ||
act_ru_deadletter_job | 作业死亡信息表,如果作业失败超过重试次数,则写入到此表 | |
act_ru_event_subscr | throwEvent、catchEvent时间监听信息表 | |
act_ru_execution | 运行时流程执行实例表 | |
act_ru_identitylink | 运行时流程人员表,主要存储任务节点与参与者的相关信息 | |
act_ru_integration | 运行时积分表 | |
act_ru_job | 定时异步任务数据表 | |
act_ru_suspended_job | 运行时作业暂停表, 比如流程中有一个定时任务,如果把这个任务停止工作了,这个任务写入到此表中 | |
act_ru_task | 运行时任务节点表 | |
act_ru_timer_job | 运行时定时器作业表 | |
act_ru_variable | 运行时流程变量数据表 |
candidateGroups
的概念
1. candidateGroups
是指任务可以分配给一组用户(即一个用户组)。在流程定义中,你可以通过 candidateGroups
指定任务的候选组。例如:
<userTask id="task1" name="Review Task" activiti:candidateGroups="managers"/>
在这个例子中,managers
是一个用户组的 ID,所有属于该组的用户都可以认领这个任务。
2. Activiti 7 中的变化
在 Activiti 7 中,candidateGroups
仍然可以在流程定义中使用,但 Activiti 7 不再提供内置的用户和组管理功能(即 IdentityService
被移除)。因此:
- 用户和组的管理:需要由外部系统(如数据库、LDAP 等)来管理。
- 任务分配:Activiti 7 仍然支持通过
candidateGroups
分配任务,但需要开发者自己实现用户和组的查询逻辑。
candidateGroups
3. 如何使用 candidateGroups
3.1 在流程定义中使用 在流程定义文件中,你可以直接使用 candidateGroups
来指定任务的候选组:
<userTask id="task1" name="Review Task" activiti:candidateGroups="managers"/>
3.2 查询候选组任务
在代码中,你可以通过 TaskService
查询属于某个组的任务:
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskService {
@Autowired
private TaskService taskService;
/**
* 查询属于某个组的任务
*/
public List<Task> getTasksForGroup(String groupId) {
return taskService.createTaskQuery()
.taskCandidateGroup(groupId) // 查询候选组任务
.list();
}
}
3.3 认领任务
如果任务是通过 candidateGroups
分配的,用户需要先认领任务才能处理:
/**
* 认领任务
*/
public void claimTask(String taskId, String userId) {
taskService.claim(taskId, userId);
}
4. 用户和组的外部管理
由于 Activiti 7 不再提供内置的用户和组管理功能,你需要自己实现用户和组的管理。例如:
4.1 数据库表设计
你可以设计以下表来管理用户和组:
CREATE TABLE users (
id VARCHAR(255) PRIMARY KEY,
username VARCHAR(255),
first_name VARCHAR(255),
last_name VARCHAR(255)
);
CREATE TABLE groups (
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255)
);
CREATE TABLE user_group (
user_id VARCHAR(255),
group_id VARCHAR(255),
PRIMARY KEY (user_id, group_id)
);
4.2 查询用户组
在查询任务时,你需要从外部系统(如数据库)获取用户所属的组:
/**
* 获取用户所属的组
*/
public List<String> getGroupsForUser(String userId) {
// 实现查询逻辑
return userGroupRepository.findGroupIdsByUserId(userId);
}
4.3 查询用户的任务
结合用户所属的组,查询用户的任务:
/**
* 查询用户的任务(包括候选组任务)
*/
public List<Task> getTasksForUser(String userId) {
// 获取用户所属的组
List<String> groupIds = getGroupsForUser(userId);
// 查询用户的任务
return taskService.createTaskQuery()
.taskCandidateOrAssigned(userId) // 用户直接分配的任务
.taskCandidateGroupIn(groupIds) // 用户所属组的任务
.list();
}
5. 总结
在 Activiti 7 中,candidateGroups
的概念仍然存在,但用户和组的管理需要由外部系统实现。你可以:
- 在流程定义中使用
candidateGroups
分配任务。 - 通过
TaskService
查询候选组任务。 - 自己实现用户和组的管理逻辑(如数据库、LDAP 等)。