最近公司需要使用工作流引擎,选用了activiti。需求中提到的流程比较简单,也就3级审核,送审时需要选择下一节点的用户,所以必须在流程中需要获取当前节点的下一个节点。代码如下:
/**
* 根据实例编号查找下一个任务节点
* @param String procInstId :实例编号
* @return
*/
public TaskDefinition nextTaskDefinition(String procInstId){
//流程标示
String processDefinitionId = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult().getProcessDefinitionId();
ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition(processDefinitionId);
//执行实例
ExecutionEntity execution = (ExecutionEntity) runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
//当前实例的执行到哪个节点
String activitiId = execution.getActivityId();
//获得当前任务的所有节点
List<ActivityImpl> activitiList = def.getActivities();
String id = null;
for(ActivityImpl activityImpl:activitiList){
id = activityImpl.getId();
if(activitiId.equals(id)){
System.out.println("当前任务:"+activityImpl.getProperty("name"));
return nextTaskDefinition(activityImpl, activityImpl.getId(),"${iscorrect==1}");
// System.out.println(taskDefinition.getCandidateGroupIdExpressions().toArray()[0]);
// return taskDefinition;
}
}
return null;
}
/**
* 下一个任务节点
* @param activityImpl
* @param activityId
* @param elString
* @return
*/
private TaskDefinition nextTaskDefinition(ActivityImpl activityImpl, String activityId, String elString){
if("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())){
TaskDefinition taskDefinition = ((UserTaskActivityBehavior)activityImpl.getActivityBehavior()).getTaskDefinition();
// taskDefinition.getCandidateGroupIdExpressions().toArray();
return taskDefinition;
}else{
List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
List<PvmTransition> outTransitionsTemp = null;
for(PvmTransition tr:outTransitions){
PvmActivity ac = tr.getDestination(); //获取线路的终点节点
if("exclusiveGateway".equals(ac.getProperty("type"))){
outTransitionsTemp = ac.getOutgoingTransitions();
if(outTransitionsTemp.size() == 1){
return nextTaskDefinition((ActivityImpl)outTransitionsTemp.get(0).getDestination(), activityId, elString);
}else if(outTransitionsTemp.size() > 1){
for(PvmTransition tr1 : outTransitionsTemp){
Object s = tr1.getProperty("conditionText");
if(elString.equals(StrUtils.trim(s.toString()))){
return nextTaskDefinition((ActivityImpl)tr1.getDestination(), activityId, elString);
}
}
}
}else if("userTask".equals(ac.getProperty("type"))){
return ((UserTaskActivityBehavior)((ActivityImpl)ac).getActivityBehavior()).getTaskDefinition();
}else{
logger.debug(ac.getProperty("type"));
}
}
return null;
}
}
思路是通过实例ID获取当前节点,然后查找当前节点后后面所有的活动,主要查找的活动是exclusiveGateway和userTask,如果exclusiveGateway中的条件符合${iscorrect==1}就直接查找exclusiveGateway后的活动,直到找到userTask为止。如果当前节点后的活动是userTask,说明这个userTask就是你想要的。
代码中${iscorrect==1}表达式是流程中定义,表示审核通过。当时对于在java中解析表达式遇到困难,所以使用字符串来比较,代码
if(elString.equals(StrUtils.trim(s.toString())))
就是用于判断表达式。后来发现可以通说juel来解析,以下是解析的代码:
ExpressionFactory factory = new ExpressionFactoryImpl();
SimpleContext context = new SimpleContext();
context.setVariable("count", factory.createValueExpression(10000, String.class));
ValueExpression e = factory.createValueExpression(context, "${count>=1000}", boolean.class);
System.out.println(e.getValue(context));