最近公司一个管理类项目需要用到流程引擎,技术选型了很久,最终选择activiti6.0.0.beta3作为本次的流程开发框架。
本次开发周期只有两个月,团队内无人对activiti有很深的了解,故记录使用过程中的问题。
本次问题的需求:要求提交报销信息后,可以根据提交人的部门信息、额度信息等动态设置审核人;
百度、谷歌了好几天,找到了不少资料,但是都是activiti 5.x的版本,而activiti 6.0对代码进行了重构,所以5.x的版本的方法并不适用。[附上5.x版本中一个比较详细的例子:http://blog.csdn.net/lovemenghaibin/article/details/50988971 ]
activiti 6.0 对实现动态配置任务节点的完成人有两种方法:
(1)通过el表达式,在bpmn.xml中设置:
<userTask id="theTask" name="my task" activiti:assignee="${person.id}"/> |
(2)通过程序来控制,实现TaskListener接口,并重写notify方法,这种方式灵活性比较大,可控性比较强。
在本次需求中,要求根据上一个任务的完成人来确定下一个任务的完成人,网上都是通过查询出流程所有的节点,然后递归比较来查找下个任务节点(因为要考虑到网关的问题),略为复杂;并且activiti 5.x中的ActivityImpl、TaskEntity等类在6.0中都没有,所以网上找的例子参考价值并不是很大;
琢磨了一天,后面还是决定从数据库的层面来搞定这个功能,因为activiti 6.0 提供了很强大的数据查询接口,实现的基本思路是:
(1)在审核任务上添加一个监听,监听审核任务的【创建(create)】事件;注意:activiti 监听会在事件执行前完成;
(2)获取对应的流程实例(ProcessInstance)Id,从历史中从查找该任务的上一个任务,并调取相应信息;
(3)根据上一个任务的信息,来判断当前审核任务需要谁审核,并设置任务接收人;
public class TaskAsigneeListener implements TaskListener {
/**
* 复写TaskListener
* */
@Override
public void notify(DelegateTask delegateTask) {
try {
NextTaskUtils taskUtils=new NextTaskUtils();
taskUtils.setTaskAsignee(delegateTask);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 设置任务的完成人
* */
public void setTaskAsignee(DelegateTask currTask) {
//获取实例ID
String processInstanceId= currTask.getProcessInstanceId();
//获取上面的多个任务
List<HistoricTaskInstance> taskList=historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().desc().list();
//获取最后面一个任务,即本任务的上一个任务
HistoricTaskInstance lastTask=taskList.get(0);
//获取上一个任务的执行人
String lastTaskAsignee=lastTask.getAssignee();
//当前任务
if(lastTaskAsignee!=null&&lastTaskAsignee.equals("zhangsan")) {
currTask.setAssignee("admin");
}else {
currTask.setAssignee("lisi");
}
}
附上activiti 6.0 的用户手册:https://www.activiti.org/userguide/
--------------------------------------------------------------------------------------------
今天(2018.3.18)测试发现仍有问题,这样动态设置任务执行人是可以,但是历史表没有同步更新,故在历史表上面新建一个触发器,来同步更新历史表中的任务完成人信息:
BEGIN
UPDATE activiti.act_hi_taskinst SET activiti.act_hi_taskinst.ASSIGNEE_=new.ASSIGNEE_ WHERE activiti.act_hi_taskinst.ID_=new.ID_;
END