activiti 选人的实现

时间:2023-03-09 18:37:01
activiti 选人的实现

activiti默认是不带有选人的功能的,它默认的是在调用complete 方法的时候自动根据下一个节点的 assignee属性或者candidate属性 设置下一节点的候选人或者 assginee。

由于项目的原因我们需要实现在上一个节点提交的时候设置就要从几个候选审批人员中选择一个或者几个审批人员,下面的代码写了个Junit 的demo。

  1. package test.java.org.activiti.designer.test;
  2. import static org.junit.Assert.*;
  3. import java.util.ArrayList;
  4. import java.util.Collection;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.io.FileInputStream;
  9. import org.activiti.bpmn.model.BpmnModel;
  10. import org.activiti.bpmn.model.FlowElement;
  11. import org.activiti.bpmn.model.Process;
  12. import org.activiti.bpmn.model.SequenceFlow;
  13. import org.activiti.engine.IdentityService;
  14. import org.activiti.engine.RepositoryService;
  15. import org.activiti.engine.RuntimeService;
  16. import org.activiti.engine.TaskService;
  17. import org.activiti.engine.impl.persistence.entity.TaskEntity;
  18. import org.activiti.engine.runtime.ProcessInstance;
  19. import org.activiti.engine.task.Task;
  20. import org.activiti.engine.test.ActivitiRule;
  21. import org.junit.Rule;
  22. import org.junit.Test;
  23. public class ProcessTest {
  24. private String filename = "E:\\workspace4.3\\kft-activiti-demo-no-maven\\resources\\diagrams\\test2.bpmn";
  25. @Rule
  26. public ActivitiRule activitiRule = new ActivitiRule();
  27. static RuntimeService runtimeService;
  28. static TaskService taskService;
  29. static IdentityService identityService;
  30. static RepositoryService repositoryService;
  31. //流程定义编号
  32. private String processDefinitionId ;
  33. //任务编号
  34. //private String taskId;
  35. //流程实例号
  36. private String processInstanceId;
  37. @Test
  38. public void mainTest() throws Exception {
  39. repositoryService = activitiRule.getRepositoryService();
  40. runtimeService = activitiRule.getRuntimeService();
  41. taskService = activitiRule.getTaskService();
  42. ProcessTest ptm = new ProcessTest();
  43. //这里有个问题,runtimeService.startProcessInstanceByKey 这个方法直接就把流程流转到任务用户去了,没经过选人的操作
  44. //这里就变通一下处理,提交到一个无所谓的人,然后在调用方法修改这个人。
  45. String taskId;
  46. //返回的usertask的id
  47. taskId = ptm.startProcess();
  48. //**********流程启动成功
  49. //流程在第一个审批人哪里
  50. //taskId = ptm.getNextNodeId(1,"feng");
  51. //选人
  52. List<String> userList= ptm.getNextTaskUserByTaskId(taskId);
  53. //设置审批人
  54. ptm.setApproveUser(taskId, "feng");
  55. taskId = ptm.getNextNodeId(1,"feng");
  56. //第一个审批人提交流程  feng 为当前节点审批人,xiaozhang 为设置的下一节点审批人
  57. ptm.completeByAssignee("feng","xiaozhang");
  58. //************第一个人审批成功
  59. taskId = ptm.getNextNodeId(1,"xiaozhang");
  60. //选人
  61. userList= ptm.getNextTaskUserByTaskId(taskId);
  62. //第一个审批人提交流程
  63. ptm.completeByAssignee("xiaozhang","xiaoming");
  64. ptm.getNextNodeId(1,"xiaoming");
  65. //第二个审批人提交流程
  66. ptm.completeByAssignee("xiaoming","xiangwang");
  67. //************第二个人审批成功
  68. }
  69. //启动流程
  70. public String startProcess() throws Exception {
  71. repositoryService.createDeployment().addInputStream("test2.bpmn20.xml",new FileInputStream(filename)).deploy();
  72. Map<String, Object> variableMap = new HashMap<String, Object>();
  73. variableMap.put("name", "Activiti");
  74. //启动流程
  75. ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("test2", variableMap);
  76. processDefinitionId = processInstance.getProcessDefinitionId();
  77. processInstance.getId();
  78. List<TaskEntity> tList =  ((org.activiti.engine.impl.persistence.entity.ExecutionEntity) processInstance).getTasks();
  79. this.setProcessInstanceId( processInstance.getId() );
  80. this.setProcessDefinitionId(processDefinitionId);
  81. if(tList.size()!=1) {
  82. System.err.println("start节点的输出路由不能有多个");
  83. }
  84. return tList.get(0).getId();
  85. }
  86. public void queryProcessInstance() {
  87. List<ProcessInstance> instanceList = runtimeService
  88. .createProcessInstanceQuery().processDefinitionKey("test")
  89. .list();
  90. //查询 流程实例
  91. for (ProcessInstance queryProcessInstance : instanceList) {
  92. queryProcessInstance.getActivityId();
  93. System.out.print("-----queryProcessInstance:"+queryProcessInstance.getActivityId());
  94. assertEquals(false, queryProcessInstance.isEnded());
  95. System.out.println("id " + queryProcessInstance.getId()
  96. + ", ended=" + queryProcessInstance.isEnded()+",ProcessDefinitionId="+queryProcessInstance.getProcessDefinitionId());
  97. }
  98. }
  99. //根据assignee来查询用户
  100. public void queryTask(String assignee) {
  101. //startProcessInstance();
  102. // taskService.createTaskQuery().taskCandidateGroup("sales").singleResult();
  103. Task task= taskService.createTaskQuery().taskAssignee(assignee).singleResult();
  104. System.out.println("审批人为【"+assignee+"】的任务有:任务编号为【" + task.getId() + "】"+ task.getTaskDefinitionKey());
  105. }
  106. /**
  107. *
  108. * @param queryType  查询类型1 根据 assignee 查询  2 根据candidateuser查询
  109. * @param str
  110. */
  111. public String getNextNodeId(int queryType,String str) {
  112. Task task = null;
  113. if(queryType==1) {
  114. task = taskService.createTaskQuery().taskAssignee(str).singleResult();
  115. }else if(queryType==2){
  116. task = taskService.createTaskQuery().taskCandidateUser(str).singleResult();
  117. }else if(queryType==3){
  118. task = taskService.createTaskQuery().taskCandidateGroup(str).singleResult();
  119. }
  120. List<FlowElement> list = getNextNode(task.getId());
  121. if(task==null) {
  122. return null;
  123. }
  124. for(FlowElement e :list) {
  125. //((org.activiti.bpmn.model.UserTask) e)
  126. }
  127. return task.getId();
  128. }
  129. /**
  130. * 获取流程的下一个节点 且要经过规则引擎判断后的节点
  131. * @param taskId
  132. * @return
  133. */
  134. private List<FlowElement> getNextNode(String taskId) {
  135. Task task = null;
  136. task = taskService.createTaskQuery().taskId(taskId).singleResult();
  137. if(task==null) {
  138. return null;
  139. }
  140. List<FlowElement> list = new ArrayList<FlowElement>();
  141. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
  142. //当前活动节点
  143. String activitiId = processInstance.getActivityId();
  144. System.out.println("当前节点是【"+activitiId+"】");
  145. //pmmnModel 遍历节点需要它
  146. BpmnModel bpmnModel =  repositoryService.getBpmnModel(task.getProcessDefinitionId());
  147. List<Process> processList = bpmnModel.getProcesses();
  148. //循环多个物理流程
  149. for(Process process:processList) {
  150. //返回该流程的所有任务,事件
  151. Collection<FlowElement> cColl = process.getFlowElements();
  152. //遍历节点
  153. for(FlowElement f :cColl) {
  154. //如果改节点是当前节点 者 输出该节点的下一个节点
  155. if(f.getId().equals(activitiId)) {
  156. List<SequenceFlow>  sequenceFlowList = new ArrayList<SequenceFlow>();
  157. //通过反射来判断是哪种类型
  158. if(f instanceof org.activiti.bpmn.model.StartEvent) {
  159. //开始事件的输出路由
  160. sequenceFlowList    = ((org.activiti.bpmn.model.StartEvent) f).getOutgoingFlows();
  161. }else if(f instanceof org.activiti.bpmn.model.UserTask) {
  162. sequenceFlowList    = ((org.activiti.bpmn.model.UserTask) f).getOutgoingFlows();
  163. for(SequenceFlow sf :sequenceFlowList)  {
  164. String targetRef = sf.getTargetRef();
  165. FlowElement ref = process.getFlowElement(targetRef);
  166. //  nextActivitiIdList.add(ref.getId());
  167. list.add(ref);
  168. }
  169. }else if(f instanceof org.activiti.bpmn.model.SequenceFlow) {
  170. }else if(f instanceof org.activiti.bpmn.model.EndEvent) {
  171. sequenceFlowList    = ((org.activiti.bpmn.model.EndEvent) f).getOutgoingFlows();
  172. }
  173. break;
  174. }
  175. }
  176. }
  177. return list;
  178. }
  179. //流程流转到下一步
  180. public void completeByAssignee(String assignee,String nextUser) throws Exception {
  181. HashMap<String,Object> map = new HashMap<String,Object>();
  182. map.put("nextUser", nextUser);
  183. Task task = taskService.createTaskQuery().taskAssignee(assignee).singleResult();
  184. taskService.complete(task.getId(),map);
  185. System.out.println("完成任务 编号为【" + task.getId() + "】,名称为【"+task.getName()+"】的任务");
  186. }
  187. /**
  188. * 设置某个节点的审批人员
  189. * @param taskId
  190. * @param user
  191. */
  192. public void setApproveUser(String taskId,String user) {
  193. Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
  194. task.setAssignee(user);
  195. taskService.saveTask(task);
  196. }
  197. /**
  198. * 取下一个节点的审批人
  199. * @param taskId
  200. * @return
  201. */
  202. public List<String> getNextTaskUserByTaskId(String taskId) {
  203. List<String> list = new ArrayList<String>();
  204. List<FlowElement> fList = getNextNode(taskId);
  205. for(FlowElement u:fList){
  206. String str =  ((org.activiti.bpmn.model.UserTask) u).getAssignee();
  207. list.add(str);
  208. }
  209. return list ;
  210. }
  211. /**
  212. * 找当前节点的候选审批人  供流程实例start后调用
  213. * @param taskId
  214. * @return
  215. */
  216. public List<String> getThisTaskUser(String taskId) {
  217. List<String> list = new ArrayList<String>();
  218. Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
  219. String taskUser = task.getAssignee();
  220. //*****************************根据taskUser的配置到自己的表里面去找数据
  221. list.add(taskUser);
  222. return list ;
  223. }
  224. public String getProcessDefinitionId() {
  225. return processDefinitionId;
  226. }
  227. public void setProcessDefinitionId(String processDefinitionId) {
  228. this.processDefinitionId = processDefinitionId;
  229. }
  230. public String getProcessInstanceId() {
  231. return processInstanceId;
  232. }
  233. public void setProcessInstanceId(String processInstanceId) {
  234. this.processInstanceId = processInstanceId;
  235. }
  236. }

另外再绘制流程图的时候除了首节点,其余每个节点要设置listener ,可以设置一个公共的listener 传递不同的参数代码如:

  1. package org.activiti.ext;
  2. import java.sql.Connection;
  3. import java.sql.ResultSet;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import javax.sql.DataSource;
  11. import org.activiti.engine.delegate.DelegateExecution;
  12. import org.activiti.engine.delegate.DelegateTask;
  13. import org.activiti.engine.delegate.ExecutionListener;
  14. import org.activiti.engine.delegate.TaskListener;
  15. import org.apache.ibatis.annotations.Delete;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18. public class TaskUserQuery implements TaskListener{
  19. /**
  20. *
  21. */
  22. private static final long serialVersionUID = 1L;
  23. private static Logger logger = LoggerFactory.getLogger(TaskUserQuery.class);
  24. protected DataSource dataSource;
  25. private org.activiti.engine.impl.el.FixedValue orgLevel ;
  26. private org.activiti.engine.impl.el.FixedValue dutyNo ;
  27. public DataSource getDataSource() {
  28. return dataSource;
  29. }
  30. public void setDataSource(DataSource dataSource) {
  31. this.dataSource = dataSource;
  32. }
  33. /**
  34. * 审批过程中找人的方法
  35. * @param str 组名
  36. * @return
  37. * @throws SQLException
  38. */
  39. public String getTaskUser(String str) throws SQLException {
  40. logger.debug("-------------------自定义找人----------------------------getTaskUser");
  41. Connection conn = dataSource.getConnection();
  42. Statement state = conn.createStatement();
  43. String queryTaskUserSql = "select id_ from act_id_user aiu where exists (select 1 from act_id_membership aim where aim.user_id_ = aiu.id_ and  aim.group_id_='"+str+"' )";
  44. ResultSet rs = state.executeQuery(queryTaskUserSql);
  45. rs.next();
  46. logger.debug("-------------------自定义找人----------------------------:返回的人是"+rs.getString(1));
  47. conn.close();
  48. state.close();
  49. return rs.getString(1);
  50. }
  51. public List<String> getTaskUserList(String str) throws SQLException {
  52. logger.debug("-------------------自定义找人----------------------------getTaskUserList");
  53. List<String> taskUser = new ArrayList<String>();
  54. Connection conn = dataSource.getConnection();
  55. Statement state = conn.createStatement();
  56. String queryTaskUserSql = "select id_ from act_id_user aiu where exists (select 1 from act_id_membership aim where aim.user_id_ = aiu.id_ and  aim.group_id_='"+str+"' )";
  57. ResultSet rs = state.executeQuery(queryTaskUserSql);
  58. while(rs.next()) {
  59. taskUser.add(rs.getString(1));
  60. }
  61. logger.debug("------------------- 自定义找人----------------------------:返回的人是"+taskUser.toString());
  62. conn.close();
  63. state.close();
  64. return taskUser;
  65. }
  66. @Override
  67. public void notify(DelegateTask delegateTask) {
  68. Map<String,Object> map = delegateTask.getVariables();
  69. String taskId = delegateTask.getId();
  70. System.out.println("in taskUserQuer class variable is:"+map.toString());
  71. System.out.println("in taskUserQuer class taskid is:"+taskId);
  72. System.out.println("in taskUserQuer class orgLevel is:"+orgLevel.getExpressionText());
  73. String id = delegateTask.getId();
  74. String s = delegateTask.getAssignee();
  75. //根据流程变量的内容设置下一个节点的审批人
  76. delegateTask.setAssignee(map.get("nextUser").toString());
  77. Map<String,Object> m1 = delegateTask.getExecution().getVariables();
  78. Map<String,Object> m2 = delegateTask.getVariablesLocal();
  79. //      logger.debug("-----------------------------------------id is:"+id);
  80. //  //  logger.debug("-----------------------------------------arg is:"+dutyNo.getExpressionText());
  81. //      delegateTask.setAssignee(dutyNo.getExpressionText());
  82. // TODO Auto-generated method stub
  83. //      logger.debug("----------------------设置选人 开始--------------------------");
  84. //      delegateTask.setAssignee("admin");
  85. //      logger.debug("----------------------设置选人 结束--------------------------");
  86. }
  87. }

整个选人过程的其实比较简单 是:提交流程的时候将下一审批人作为流程变量提交到流程引擎,流程引擎会调用如上代码块的notify 方法(当然需要在usertask上配置 配置下图) ,在notify方法内delegateTask.setAssignee设置下一个节点的审批人

activiti 选人的实现