Flowable 监听器的使用
需求背景:
1、发起人发起流程,可以实现发起人自动审核
2、上一节点的审核人,与当前节点审核人相同时,自动审核
3、整个流程实例中,存在已审核的审核人,当前节点自动审核
流程图如下所示:
针对于自动审核设置,其实是由前端内置bpnm.xml 去设置的,与前端达成协议,例如不启用时,就不要置入监听器,启用时,就植入监听器,在配置不同的字段,表示不同的审核方式。
发起人自动审核
自定义监听器,实现TaskListener,并配置需要的字段,该字段与前端的需要达成一致
bpmn.xml 如下:
这样在监听器下就可以接受到这两个字段的值,根据这两个字段的值,去完成自动审核功能。
值得注意的是,在监听器中,spring的自动注入并不能通过注解 @Autowired 去实现,而且通过构造函数加spring的上下文去实现注入。
例如:
重写TaskListener 的 notify 方法,该方法的形参是DelegateTask,这个参数可以获取到bpnm.xml 中 任务节点的属性,例如监听器的字段,任务id,流程实例id,流程定义等等。基于这个现有条件,我们即可完成发起人自动审核。
@Override
public void notify(DelegateTask delegateTask) {
// 从 FixedValue 中获取值
String autoApprovalEnabledStr = (String) autoApprovalEnabled.getValue(delegateTask);
String autoApprovalRuleStr = (String) autoApprovalRule.getValue(delegateTask);
String processDefinitionId = delegateTask.getProcessDefinitionId();
String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
String eventName = delegateTask.getEventName();
logger.info("触发监听器,当前监听器级别:{}",eventName);
logger.info("触发监听器,当前任务:{}",delegateTask.getName());
UserTask userTask = (UserTask) bpmnModel.getFlowElement(taskDefinitionKey);
createLevelAutoTask(userTask,delegateTask,autoApprovalRuleStr,autoApprovalEnabledStr);
}
在 createLevelAutoTask 方法中,需要完成以下步骤,判断当前的任务节点是不是会签节点,针对与会签节点,我们不去实现自动审核,直接停止当前监听器即可,还需要考虑,发起人如果是角色,或者是部门的情况下,我们应该怎么去实现,同样的,发起人是单个用户的话怎么实现,针对单个用户非常简单。
private void createLevelAutoTask(UserTask userTask, DelegateTask delegateTask, String autoApprovalRuleStr, String autoApprovalEnabledStr) {
// 检查会签任务
Integer nrOfInstances = (Integer) delegateTask.getVariable("nrOfInstances");
Integer nrOfCompletedInstances = (Integer) delegateTask.getVariable("nrOfCompletedInstances");
if (nrOfInstances != null && nrOfCompletedInstances != null) {
// 这是一个多实例任务
return;
}
if (userTask !=null){
// 获取 当前任务节点的 类型,部门 DEPTS 、角色 ROLES
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
// 获取组的ID,角色ID集合或部门ID集合
List<Long> groups = userTask.getCandidateGroups().stream()
.map(item -> Long.parseLong(item.substring(4)))
.collect(Collectors.toList());
List<Long> userIds = new ArrayList<>();
// 分别处理发起人是角色,部门,和user的场景
if ("ROLES".equals(dataType) && !groups.isEmpty()){
UserGroupRoleBO userGroupRoleBO = new UserGroupRoleBO();
userGroupRoleBO.setRoleIdList(groups);
userGroupRoleBO.setOrgIdList(null);
userIds = userRemote.findUserByOrgIdsOrByRoleIds(userGroupRoleBO);
// 表示启用自动审核
if (AutoProcessType.AUTO_RULE_ENABLE.getCode().equals(autoApprovalEnabledStr)) {
handleAutoApproval1(delegateTask, autoApprovalRuleStr,userIds);
}
}else if("DEPTS".equals(dataType) && !groups.isEmpty()){
UserGroupRoleBO userGroupRoleBO = new UserGroupRoleBO();
userGroupRoleBO.setRoleIdList(null);
userGroupRoleBO.setOrgIdList(groups);
userIds = userRemote.findUserByOrgIdsOrByRoleIds(userGroupRoleBO);
// 表示启用自动审核
if (AutoProcessType.AUTO_RULE_ENABLE.getCode().equals(autoApprovalEnabledStr)) {
handleAutoApproval1(delegateTask, autoApprovalRuleStr,userIds);
}
}else {
if (AutoProcessType.AUTO_RULE_ENABLE.getCode().equals(autoApprovalEnabledStr)){
handleAutoApproval(delegateTask, autoApprovalRuleStr);
}
}
}
}
直接从单个用户来说吧,对于部门和角色相差不差,只需要获取到部门的id或者角色id,通过服务调用的方式去拿到用户的id,判断当前的登录用户是否在这个用户id集合中,存在即自动审核就好。
以下是针对单个用户的实现代码
@Transactional
public void handleAutoApproval(DelegateTask delegateTask, String autoApprovalRule) {
String processInstanceId = delegateTask.getProcessInstanceId();
Map<String, Object> variables = delegateTask.getVariables();
String taskId = delegateTask.getId();
String assignee = delegateTask.getAssignee();
String currentAssignee = (String) variables.get(ProcessConstants.CURRENT_ASSIGNEE);
// 每一次任务审核,存储审核人的id
List<String> assigneeList = (ArrayList) variables.get(ProcessConstants.ASSIGNEE_LIST) == null?new ArrayList<>():(ArrayList) variables.get("assigneeList") ;
String userIdStr = (String) variables.get(ProcessConstants.PROCESS_INITIATOR);
UserToken userToken = AuthorizationContext.getAdminUser();
String userId = userToken.getUserId().toString();
NodeUserVO uservo = userRemote.findUserById(Long.parseLong(assignee));
String nickname = uservo.getNickname();
String msg = AutoProcessType.AUTO_INITIATOR_ENABLE.getCode().equals(autoApprovalRule)?nickname + "发起流程申请":nickname+"通过";
// 发起人自动审核
if (AutoProcessType.AUTO_INITIATOR_ENABLE.getCode().equals(autoApprovalRule)) {
if (userId.equals(userIdStr)) {
assigneeList.add(userIdStr);
variables.put(ProcessConstants.CURRENT_ASSIGNEE,userId);
variables.put(ProcessConstants.ASSIGNEE_LIST,assigneeList);
commentTask(userId, taskId, processInstanceId, FlowComment.NORMAL.getType(), msg, variables, delegateTask);
}
} else if (AutoProcessType.AUTO_ADJACENT_ENABLE.getCode().equals(autoApprovalRule)) {
// if (checkPreviousAssignee(assignee, delegateTask)) {
// variables.put("currentAssignee",String.valueOf(userId));
// variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
// commentTask(userId, taskId, processInstanceId, FlowComment.SKIP.getType(), msg, variables, delegateTask);
// }
// 判断 上一节点 审批人 与当前节点审批人是否一致
if (StringUtils.isNotBlank(currentAssignee) && currentAssignee.equals(assignee)) {
variables.put(ProcessConstants.CURRENT_ASSIGNEE,userId);
assigneeList.add(userIdStr);
variables.put(ProcessConstants.ASSIGNEE_LIST,assigneeList);
variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
commentTask(userId, taskId, processInstanceId, FlowComment.SKIP.getType(), msg, variables, delegateTask);
}
} // 表示 当前流程实例中,存在已审核过的审核人,自动审核
else if (AutoProcessType.AUTO_APPROVED.getCode().equals(autoApprovalRule)){
// 相同表示 已存在审核人了
if (assigneeList.contains(userId)){
msg = nickname + "通过";
variables.put(ProcessConstants.CURRENT_ASSIGNEE,userId);
assigneeList.add(userIdStr);
variables.put(ProcessConstants.ASSIGNEE_LIST,assigneeList);
variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
commentTask(userId, taskId, processInstanceId, FlowComment.SKIP.getType(), msg, variables, delegateTask);
}
}
}
private void commentTask(String userId,String taskId,String processInId,String commentType,String message, Map<String, Object> variables ,DelegateTask delegateTask){
identityService.setAuthenticatedUserId(userId);
taskService.addComment(taskId, processInId, commentType, message);
logger.info("已完成任务:{}",delegateTask.getName());
taskService.complete(taskId, variables);
}
主要的实现方式,通过设置流程变量的方式,在流程发起的时候,去判断当前登录用户与任务节点受理用户的id是否一致,如果一致就自动审核即可,对于上一节点和当前节点审核人相同自动审核的,在用户审核时,添加流程变量,那么这个流程实例就存储了当前的审核人信息,在下一个任务时,判断以下是否一致即可。就不写那么详细了。
标签:String,delegateTask,Flowable,variables,userId,ProcessConstants,审核,节点 From: https://www.cnblogs.com/zgf123/p/18350897