实际工作中,待办事项一般是通过用户ID进行查询的,这样比较简单、方便。在Activiti中,当绘制流程的人工任务节点时,为了便于日后维护,也为了更符合实际的场景,通常不会直接指定受理人,而是指定候选组,也就是通常说的角色。而很多时候,这个角色只有一个用户,但是在Activiti的实现中,这里面需要一个中间环节,就是签收,这个签收的过程,显得不够智能,用户会很自然的觉得多此一举,多了一步没必要的操作,那么能不能把这个环节省掉呢?本文将提供解决这个问题的方法。
这个问题,只能研究下Activiti的源代码了,如果能找到扩展点,那这个问题就好办了,经过研究,发现并不难,工作量也不大,下面进行详细说明(本文前提是Activiti与Spring集成,其他环境请自行举一反三)。
一、自定义DefaultActivityBehaviorFactory,自定义该类的目的是创建自定义的UserTaskActivityBehavior,自定义的DefaultActivityBehaviorFactory需要通过set方法注入到SpringProcessEngineConfiguration中;
二、自定义UserTaskActivityBehavior,通过扩展handleAssignments方法,对于受理人、候选人和候选组进行处理。这里面需要注意的是,至于如何确定一个候选组只有一个用户,如何获取这个唯一的用户,开发者需要自行确定,下面的样例代码仅供参考。
import org.activiti.bpmn.model.UserTask; import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior; import org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory; import org.activiti.engine.impl.task.TaskDefinition; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class ProcessActivityBehaviorFactory extends DefaultActivityBehaviorFactory implements ApplicationContextAware{ private ApplicationContext applicationContext; @Override public UserTaskActivityBehavior createUserTaskActivityBehavior( UserTask userTask, TaskDefinition taskDefinition) { ProcessUserTaskActivityBehavior taskActivityBehavior = (ProcessUserTaskActivityBehavior)applicationContext.getBean("taskActivityBehavior"); taskActivityBehavior.setTaskDefinition(taskDefinition); return taskActivityBehavior; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
import java.util.Collection; import java.util.List; import java.util.Map; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; import org.activiti.engine.TaskService; import org.activiti.engine.delegate.Expression; import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.task.TaskDefinition; import org.springframework.beans.factory.annotation.Autowired; public class ProcessUserTaskActivityBehavior extends UserTaskActivityBehavior { @Autowired private TaskService taskService; public ProcessUserTaskActivityBehavior() { super(null); } public void setTaskDefinition(TaskDefinition taskDefinition){ super.taskDefinition = taskDefinition; } public ProcessUserTaskActivityBehavior(TaskDefinition taskDefinition) { super(taskDefinition); } @Override protected void handleAssignments(TaskEntity task,ActivityExecution execution) { String assignee = null; List<String> candidateUserId = null,candidateGroupId = null; if (taskDefinition.getAssigneeExpression() != null) { assignee = (String) taskDefinition.getAssigneeExpression().getValue(execution); task.setAssignee(assignee,true,false); } if (taskDefinition.getOwnerExpression() != null) { task.setOwner((String) taskDefinition.getOwnerExpression().getValue(execution)); } if (!taskDefinition.getCandidateGroupIdExpressions().isEmpty()) { for (Expression groupIdExpr : taskDefinition.getCandidateGroupIdExpressions()) { Object value = groupIdExpr.getValue(execution); if (value instanceof String) { candidateGroupId = extractCandidates((String) value); task.addCandidateGroups(candidateGroupId); } else if (value instanceof Collection) { task.addCandidateGroups((Collection) value); } else { throw new ActivitiIllegalArgumentException("Expression did not resolve to a string or collection of strings"); } } } if (!taskDefinition.getCandidateUserIdExpressions().isEmpty()) { for (Expression userIdExpr : taskDefinition.getCandidateUserIdExpressions()) { Object value = userIdExpr.getValue(execution); if (value instanceof String) { candidateUserId = extractCandidates((String) value); task.addCandidateUsers(candidateUserId); } else if (value instanceof Collection) { task.addCandidateUsers((Collection) value); } else { throw new ActivitiException("Expression did not resolve to a string or collection of strings"); } } } if (assignee == null && candidateUserId == null && candidateGroupId.size() ==1){ String groupId = candidateGroupId.get(0); //下面的代码开发者自行确定处理方法 String sql = "SELECT USER_ID FROM SYS_ROLE_USER WHERE ROLE_ID = ‘" + groupId + "‘ AND ROLE_TYPE = ‘3‘"; CoreTemplate coreTemplate = CoreContextContainer.getContext().getCoreTemplate(); List data = coreTemplate.find(sql,null,true); if (data.size() == 1){ String userId = (String)((Map)data.get(0)).get("user_id"); taskService.claim(task.getId(),userId);//符合条件的自动签收 } } } }
下面是对应的Spring配置文件,这里面特别需要注意的是,taskActivityBehavior不能是单例的,相应的scope值为prototype。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <bean id="processEngineConfiguration" class="com.process.ProcessEngineConfiguration"> <property name="activityBehaviorFactory" ref="activityBehaviorFactory"/> </bean> <bean id="activityBehaviorFactory" class="com.process.ProcessActivityBehaviorFactory"/> <bean id="taskActivityBehavior" class="com.process.ProcessUserTaskActivityBehavior" scope="prototype"/> </beans>
以上代码在Activiti5.15.1版本中测试通过。
时间: 2024-10-09 07:26:26