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. Java中关于CountDownLatch的使用

    CyclicBarrier工具类主要是控制多个线程的一起执行,演示程序: import java.util.Random; import java.util.concurrent.CountDownL ...

  2. win10下SVN图标不显示

    win10系统的SVN图标不现实了.正常情况下,会在文件夹上有一个对勾 但是对勾以及所有的SVN图标都突然消失了,都不知道文件什么状态了. 经过一通搜索,发现问题所在(都指向注册表图标被占用).原因就 ...

  3. 在Debian系中快速有效的安装oracle-java

    jre8下载链接  https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html oracl ...

  4. leetcode 199. Binary Tree Right Side View 、leetcode 116. Populating Next Right Pointers in Each Node 、117. Populating Next Right Pointers in Each Node II

    leetcode 199. Binary Tree Right Side View 这个题实际上就是把每一行最右侧的树打印出来,所以实际上还是一个层次遍历. 依旧利用之前层次遍历的代码,每次大的循环存 ...

  5. leetcode701. Insert into a Binary Search Tree

    https://www.cnblogs.com/grandyang/p/9914546.html 类似于二分查找的方法,用迭代的方法去做 注意:无论是进入左子树还是右子树,左右子树都变成了新的数,所以 ...

  6. 使用scrapy爬取海外网学习频道

    一:创建项目文件 1:首先在终端使用命令scrapy startproject huaerjieribao 创建项目 2:创建spider 首先cd进去刚刚创建的项目文件overseas 然后执行ge ...

  7. hibernate validator 动态返回国际化提示

    一.说明 以下方法实现了读取指定国际化文件的校验器. 1. MyMessages是自定义的国际化文件,放置在src的根目录下 例如有MyMessages_en_US.properties.MyMess ...

  8. docker安装jdk8

    1.下载jdk8 wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.or ...

  9. Android学习之基础知识七—碎片的最佳实践

    一.Android碎片(Fragment)的最佳实践——简易版新闻应用 第一步:新建FragmentBestPractice项目,在app/build.gradle当中添加:RecyclerView ...

  10. Android Studio在华为真机上运行无法输出Debug日志解决

    这主要与华为手机本身的权限设置有关,解决办法请看链接地址 链接地址: https://blog.csdn.net/seafishyls/article/details/52198814