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 选人的实现的更多相关文章

  1. Activiti流程编辑器针对自定义用户角色表优化改造

    本文目的: 针对自定义的用户.角色表,对Activiti的在线流程设计器进行优化改造,使之能直接在图形界面上完成对节点办理人.候选人.候选组的配置,不需要先去查数据库中的用户ID.角色ID等信息再填入 ...

  2. 流程开发Activiti 与SpringMVC整合实例

    流程(Activiti) 流程是完成一系列有序动作的概述.每一个节点动作的结果将对后面的具体操作步骤产生影响.信息化系统中流程的功能完全等同于纸上办公的层级审批,尤其在oa系统中各类电子流提现较为明显 ...

  3. activiti工作流的web流程设计器整合视频教程 SSM和独立部署

    本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...

  4. activiti工作流的web流程设计器整合视频教程 SSM 和 独立部署

    本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...

  5. 文档分享-Activiti 5.16 用户手册

    今天在翻看工作流相关的网页的时候,在开源中国上http://www.oschina.net/question/915507_149175发现activiti的中文文档:http://www.mossl ...

  6. 1. Activiti 运行时表信息总结

    Activiti的后台是有数据库的支持,所有的表都以ACT_开头. 第二部分是表示表的用途的两个字母标识. 用途也和服务的API对应. ACT_RE_*: 'RE'表示repository. 这个前缀 ...

  7. Activiti学习(二)数据表结构

    Activiti工作流引擎数据库表结构 数据库表的命名 Acitiviti数据库中表的命名都是以ACT_开头的.第二部分是一个两个字符用例表的标识.此用例大体与服务API是匹配的. l        ...

  8. Activiti学习(一) 环境搭建

    原料:Activiti5.4  MyEclipse 10 1.先将activiti文件夹放置myeclipse的安装目录dropins文件夹下2.将activiti文件夹里activiti.link中 ...

  9. Activiti工作流学习(三)Activiti工作流与spring集成

    一.前言 前面Activiti工作流的学习,说明了Activiti的基本应用,在我们开发中可以根据实际的业务参考Activiti的API去更好的理解以及巩固.我们实际的开发中我们基本上都使用sprin ...

随机推荐

  1. 【洛谷】【最小生成树】P1536 村村通

    [题目描述:] 某市调查城镇交通状况,得到现有城镇道路统计表.表中列出了每条道路直接连通的城镇.市政府"村村通工程"的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路 ...

  2. HDU - 4336 (容斥)

    题意:给你n个奖,每个机会只能中一个奖,中奖的概率分别是{p1,p2,p3......pn}:并且这些奖是两两没有交集.(pi*pj=0)问,需要多少次才能把所有奖都中完的期望值. 先来分析:中所有奖 ...

  3. Scout YYF I POJ - 3744(矩阵优化)

    题意:一条路上有n个地雷,给出地雷的位置.某人从起点(位置1)出发,走一步的概率是p,走两步的概率是(1-p),然后问有多少概率走过这个雷区. 思路: 只要走过最后一个地雷就代表走过雷区了. 而每到 ...

  4. esp8266(0) AT指令

    http://www.shaoguoji.cn/2017/01/15/ESP8266-usage/ 注意事项 使用WiFi模块的一些细节及注意事项 模块使用3.3V供电,一定注意电源的稳定,一些USB ...

  5. QT 11 鼠标键盘事件添加

    鼠标事件 void mousePressEvent(QMouseEvent *event); //单击 void mouseReleaseEvent(QMouseEvent *event); //释放 ...

  6. Qt 编程指南 3 信号和槽沟通

    https://qtguide.ustclug.org/ 1 信号和槽 所谓信号槽,简单来说,就像是插销一样:一个插头和一个插座.怎么说呢?当某种事件发生之后,比如,点击了一下鼠标,或者按了某个按键, ...

  7. 扫描Linux服务器查找恶意软件和rootkit的一款工具

    官网参考官网安装教程:wget https://www.clamav.net/downloads/production/clamav-0.101.1.tar.gztar -zxvf clamav-0. ...

  8. AI 概率论

    概率论 不确定性 量化 频率 频率派 贝叶斯派 1.随机变量(random variable) 随机取不同值的变量,取值可以离散或者连续. 2.概率分布(probability distributio ...

  9. 洛谷 P1525 关押罪犯

    题目链接 https://www.luogu.org/problemnew/show/P1525 题目描述 S城现有两座监狱,一共关押着N名罪犯,编号分别为1−N.他们之间的关系自然也极不和谐.很多罪 ...

  10. SkylineGlobe Android 开发 面积计算示例代码

    SkylineGlobe Android 开发 面积计算示例代码: 如果之前熟悉SkylineGlobe桌面端的二次开发,看这些代码应该不难理解. package com.skyline.terrae ...