Activiti会签、选人页面的实现
Activiti
1、背景
Activiti默认是不带有选人的功能的,它默认的是在调用complete方法的时候自动根据下一个节点的 assignee属性设置下一节点的候选人,也可设置candidate属性或者角色,提交到下一步,流程引擎自动解析为公有任务,需要具体执行人去认领。
但是并不是所有的业务逻辑都符合Activit规定的标准情况,适用于这种操作,用户提交时需要从几个候选人中选择一个,然后发送到下一个环节,被选择的审批人,在下一环节拥有待办,目前Activiti工作流暂不支持原生支持,需要自己扩展。
Activiti 工作流会签开发设计思路
在流程业务管理中,任务是通常都是由一个人去处理的,而多个人同时处理一个任务,这种任务我们称之为会签任务。这种业务需求也很常见,如一个请款单,领导审批环节中,就需要多个部门领导签字。在流程业务中,我们可以把每个领导签字的环节都定义为任务,但若这样,这个流程业务有一点是固定的,就是签批人是固定的。而任务是由一个领导签完再到另一领导,当然也可以由多个领导同时签字。
传统的用流程业务来解决可以采用以下的做法:
串行会签:
并行会签:
前者在流程业务中,叫串行会签,也即是由一个领导签完再至另一领导签。后者我们称之为并行会签,表示几个领导同时进行签发,而不清楚最终是谁先签。
以上的解决方式有两大业务需求下是不能满足的,若会签的领导不是固定的,即可以由上一任务审批人提交前随意进行选择,另一种是对于会签业务中,要求若其中一部分领导审批通过,即直接往下走,不需要全部领导进行审批。另外,对于这种情况下,统计最终领导会签的结果也是比较困难的,即对审批单的意见是同意还是否决没有办法清楚。以上两种业务需求也是很常见的日常需求,但我们若采用了固定的流程节点,则不能实现。在这里,可以采用Activiti的节点多实例来处理,以上流程则可以简化为下:
2、扩展步骤
1、实现原理
1、目前Activiti人员解析逻辑
Activiti自带了23张表,其中有四张组织人员相关表:
1) act_id_group用户组信息表
2) act_id_info用户扩展信息表
3) act_id_membership用户与用户组对应信息表
4) act_id_user用户信息表
原生的Activiti人员解析,需要依赖Activiti内置的四张组织信息表,也提供了一些列的AIP让我们去操作这些表,插入和获取信息。
Activiti本身自带了简易的人员管理功能,角色配置,原生的做法是将人员和角色信息配置到工作流表中,工作流就可以自动解析环节处理时的角色,转换为为处理人,我们具体业务实现不用处理,但是这直接导致了三个问题:
第一:就是工作流自带的人员角色表过于简单,不一定能应对复杂的业务逻辑需求。
第二:需要维护两套人员角色信息,加重了程序设计的复杂性。
第三:不便于扩展,业务程序对工作流人员解析这块完全没有控制权,无法做到选人等业务需求。
2、如何使用自己的选人逻辑
首先我们无需管这四张表,也不 用往这些表中插入任何数据,这样就可以使Actriviti基于角色的选人失效,因为根据角色无法解析到人员。
实现我们自己的选人,同样依赖与流程图的属性配置,具体的逻辑是:
流程图配置好审批角色后,业务逻辑程序在提交下一步之前,提前获取到下一步的审批环节和审批角色,手工解析为多个人员,展示给用户,让其选择一个或多个,再以流程参数的形式设置到流程中,提交下一步,下一步审批环节识别到流程参数,绑定审批人员。
2、具体实现
1、编写流程定义工具类
用户获取流程定义相关信息,ActDefinitionService.java示例为:
package modules.act.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import common.utils.StringUtils;
import modules.act.entity.ActTransition;
/**
* 流程定义Service
- */
@Service
@Transactional(readOnly = true)
public class ActDefinitionService {
@Autowired