系列文章目录(springboot整合activiti5)

并行网关,出来的分支不需要带任何条件,每个分支都需要运行,然后汇聚到并行网关。在Activiti中,并行网关的XML代码基本格式如下

<parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway>

流程图如下

对于并行网关不需要设置任何条件,即使设置了条件也不会起作用,对于到并行网关汇聚的分支,只有所有待汇聚的分支都运行结束后,才会进入到下一个节点,对于上面的案例来说,只有部门领导审批和财务部门审批同时完成之后,才会进入到审批人确认的任务。
完整的流程定义reimbursement-8.bpmn

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.zioer.com/reimbursement-8"><process id="reimbursement-8" name="费用报销-8" isExecutable="true"><startEvent id="startevent1" name="Start" activiti:initiator="startUserId" activiti:formKey="start.form"></startEvent><userTask id="usertask1" name="部门领导审批" activiti:candidateGroups="leadergroup" activiti:formKey="conform1.form"></userTask><userTask id="usertask2" name="财务部门审批" activiti:candidateGroups="feegroup" activiti:formKey="conform2.form"></userTask><userTask id="usertask3" name="申请人确认" activiti:assignee="${startUserId}" activiti:formKey="conform3.form"></userTask><parallelGateway id="parallelgateway1" name="Parallel Gateway"></parallelGateway><sequenceFlow id="flow1" sourceRef="startevent1" targetRef="parallelgateway1"></sequenceFlow><sequenceFlow id="flow2" sourceRef="parallelgateway1" targetRef="usertask1"></sequenceFlow><sequenceFlow id="flow3" sourceRef="parallelgateway1" targetRef="usertask2"></sequenceFlow><parallelGateway id="parallelgateway2" name="Parallel Gateway"></parallelGateway><sequenceFlow id="flow4" sourceRef="usertask1" targetRef="parallelgateway2"></sequenceFlow><sequenceFlow id="flow5" sourceRef="usertask2" targetRef="parallelgateway2"></sequenceFlow><sequenceFlow id="flow6" sourceRef="parallelgateway2" targetRef="usertask3"></sequenceFlow><endEvent id="endevent1" name="End"></endEvent><sequenceFlow id="flow7" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_reimbursement-8"><bpmndi:BPMNPlane bpmnElement="reimbursement-8" id="BPMNPlane_reimbursement-8"><bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"><omgdc:Bounds height="35.0" width="35.0" x="109.0" y="147.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"><omgdc:Bounds height="55.0" width="105.0" x="280.0" y="90.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"><omgdc:Bounds height="55.0" width="105.0" x="280.0" y="181.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3"><omgdc:Bounds height="55.0" width="105.0" x="520.0" y="137.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="parallelgateway1" id="BPMNShape_parallelgateway1"><omgdc:Bounds height="40.0" width="40.0" x="190.0" y="144.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="parallelgateway2" id="BPMNShape_parallelgateway2"><omgdc:Bounds height="40.0" width="40.0" x="430.0" y="144.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"><omgdc:Bounds height="35.0" width="35.0" x="680.0" y="147.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"><omgdi:waypoint x="144.0" y="164.0"></omgdi:waypoint><omgdi:waypoint x="190.0" y="164.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"><omgdi:waypoint x="210.0" y="144.0"></omgdi:waypoint><omgdi:waypoint x="210.0" y="117.0"></omgdi:waypoint><omgdi:waypoint x="280.0" y="117.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"><omgdi:waypoint x="210.0" y="184.0"></omgdi:waypoint><omgdi:waypoint x="210.0" y="208.0"></omgdi:waypoint><omgdi:waypoint x="280.0" y="208.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"><omgdi:waypoint x="385.0" y="117.0"></omgdi:waypoint><omgdi:waypoint x="450.0" y="117.0"></omgdi:waypoint><omgdi:waypoint x="450.0" y="144.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"><omgdi:waypoint x="385.0" y="208.0"></omgdi:waypoint><omgdi:waypoint x="450.0" y="208.0"></omgdi:waypoint><omgdi:waypoint x="450.0" y="184.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"><omgdi:waypoint x="470.0" y="164.0"></omgdi:waypoint><omgdi:waypoint x="520.0" y="164.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7"><omgdi:waypoint x="625.0" y="164.0"></omgdi:waypoint><omgdi:waypoint x="680.0" y="164.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

创建一个控制器

package com.xquant.platform.test.activiti.controller;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricDetail;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;/*** 并行网关*/
@Controller
@RequestMapping(value = "/paragateform")
public class ParagateformController {@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate FormService formService;@Autowiredprivate TaskService taskService;@Autowiredprivate IdentityService identityService;@Autowiredprivate HistoryService historyService;@Autowiredprivate RuntimeService runtimeService;@RequestMapping(value = "/add")public String add(Model model,HttpSession session) {if (session.getAttribute("userId") == null){return "redirect:/login/";}ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("reimbursement-8").latestVersion().singleResult();Object startForm = formService.getRenderedStartForm(processDefinition.getId());model.addAttribute("formData", startForm);return "reimbursement-5_start";}/*** 提交启动流程*/@RequestMapping(value = "/start/save")public String saveStartForm(Model model,HttpServletRequest request,HttpSession session) {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}Map formProperties = PageData(request);ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("reimbursement-8").latestVersion().singleResult();String processDefinitionId = processDefinition.getId();try {identityService.setAuthenticatedUserId(userId);formService.submitStartFormData(processDefinitionId, formProperties);} finally {identityService.setAuthenticatedUserId(null);}return "redirect:/paragateform/list";}@RequestMapping(value = "/list")public String list(Model model,HttpSession session) {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}List<Task> tasks = new ArrayList<Task>();//获得当前用户的任务tasks = taskService.createTaskQuery().processDefinitionKey("reimbursement-8").taskCandidateOrAssigned(userId).active().orderByTaskId().desc().list();model.addAttribute("list", tasks);return "reimbursement-5_list";}/*** 任务签收*/@RequestMapping(value = "/claim/{taskId}")public String claim(@PathVariable("taskId") String taskId, HttpSession session) {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}taskService.claim(taskId, userId);return "redirect:/paragateform/list";}/*** 初始化启动流程,读取启动流程的表单字段来渲染start form*/@RequestMapping(value = "/startform/{taskId}")public String StartTaskForm(@PathVariable("taskId") String taskId,Model model,HttpSession session) throws Exception {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}Object taskForm = formService.getRenderedTaskForm(taskId);        String startUserId = (String) taskService.getVariable(taskId, "startUserId"); model.addAttribute("formData", taskForm);model.addAttribute("taskId", taskId);model.addAttribute("startUserId", startUserId);return "reimbursement-5_edit";}/*** 提交启动流程*/@RequestMapping(value = "/startform/save/{taskId}")public String saveTaskForm(@PathVariable("taskId") String taskId,HttpSession session,HttpServletRequest request) {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}Map formProperties = PageData(request);try {identityService.setAuthenticatedUserId(userId);formService.submitTaskFormData(taskId, formProperties);} finally {identityService.setAuthenticatedUserId(null);}return "redirect:/paragateform/list";}@RequestMapping(value = "/hlist")public String historylist(Model model,HttpSession session) {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}List<Map> hlist = new ArrayList<Map>();List historylist = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("reimbursement-8").startedBy(userId).list();for (int i=0;i<historylist.size();i++){Map<String, Object> map = new HashMap<String, Object>();HistoricProcessInstanceEntity hpe = (HistoricProcessInstanceEntity) historylist.get(i);map.put("id", hpe.getId());map.put("startUserId", hpe.getStartUserId());map.put("processInstanceId", hpe.getProcessInstanceId());map.put("endTime", hpe.getEndTime());map.put("startTime", hpe.getStartTime());if (hpe.getEndTime() == null){List<Task> taskList =  taskService.createTaskQuery().processInstanceId(hpe.getProcessInstanceId()).active().list();String taskName = "";for (int j=0;j<taskList.size();j++){if (taskList.get(j) != null){taskName = taskName == "" ? taskList.get(j).getName() : taskName + "," + taskList.get(j).getName(); }}if (taskName != ""){map.put("name", taskName);}}else{map.put("name", "已完成");}hlist.add(map);}//获得当前用户的任务model.addAttribute("list", hlist);return "reimbursement_hlist";}@RequestMapping(value = "/hview/{pId}")public String historyView(@PathVariable("pId") String pId,Model model,HttpSession session) {String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();if (userId == null){return "redirect:/login/";}List<HistoricDetail> details = historyService.createHistoricDetailQuery().processInstanceId(pId).orderByTime().asc().list();model.addAttribute("list", details);return "reimbursement_hview";}public Map PageData(HttpServletRequest request){Map properties = request.getParameterMap();Map returnMap = new HashMap(); Iterator entries = properties.entrySet().iterator(); Map.Entry entry; String name = "";  String value = "";  while (entries.hasNext()) {entry = (Map.Entry) entries.next(); name = (String) entry.getKey(); Object valueObj = entry.getValue(); if(null == valueObj){ value = ""; }else if(valueObj instanceof String[]){ String[] values = (String[])valueObj;for(int i=0;i<values.length;i++){ value = values[i] + ",";}value = value.substring(0, value.length()-1); }else{value = valueObj.toString(); }returnMap.put(name, value); }return returnMap;}}

除了流程定义不一样之外,还有一个地方需要注意,对于以前的模式,在同一时刻流程实例中只有一个task处于激活状态。所以通过taskService.createTaskQuery().processInstanceId(hpe.getProcessInstanceId()).active()查询的结果只会有一个,而在当前的并行网关当中,会出现多个激活的任务,所以在查询历史任务的时候,当前节点需要考虑多个值的拼接问题。

对应源码部分改动如下

通过http://localhost:8080/paragateform/add发起一个新的流程




可以看到此时当前任务同时进入了部门领导审批和财务部门审批的阶段了。
接下来完成财务部门的审批操作

剩下财务部门进行办理了

执行办理并提交

申请人确认

从以上流程不难看出出并行网关的特点:对于并行网关汇聚的分支,只有所有待汇聚的分支都运行结束之后,才会流入到下一个节点。

SpringBoot整合activiti5-并行网关相关推荐

  1. SpringBoot 整合activiti5.22 实现一个完整的请假流程

    最近在熟悉activiti的使用,翻阅了很多资料,自己也整理了一点出来方便以后自己使用 一.引入依赖 <dependencies><dependency><groupId ...

  2. SpringBoot整合activiti5-业务表单

    系列文章目录(springboot整合activiti5) 在实际的开发当中,除了简单的业务逻辑之外,还有更为复杂的业务,例如常见的主从表单,总之采用Activiti的内置表单和外置表单方式无法满足所 ...

  3. 全网最新Spring Boot2.5.1整合Activiti5.22.0企业实战教程<网关篇>

    文章目录 前言 一.网关概念 二.网关类型 1.排它网关(独占网关) 1.部署流程 1.1 经理审批(李四) 1.2 董事长审批(王五) 1.3 部署流程代码 2.启动流程 3.执行任务 2.并行网关 ...

  4. Activiti工作流使用之SpringBoot整合Activiti

    Activiti工作流使用之SpringBoot整合Activiti 文章目录 Activiti工作流使用之SpringBoot整合Activiti 一.springboot整合Activiti环境依 ...

  5. 一小时学会使用Springboot整合沙箱环境支付宝支付(附源码)

    0.前言 文章需求: 对于学生来说,目前网上确实没有比较统一而且质量好的支付教程.因为支付对个人开发者尤其是学生来说不太友好.因此,自己折腾两天,算是整理了一篇关于支付宝沙箱支付的文章. 那么为什么不 ...

  6. SpringBoot整合Sa-Token

    SpringBoot整合Sa-Token 入门介绍 技术理论 技术实践 入门介绍 Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证.权限认证.Session会话.单点登录.OAut ...

  7. SpringBoot整合Guacamole

    前言 本文主要介绍的是SpringBoot如何整合Guacamole在浏览器是远程桌面的访问. Guacamole 介绍 Apache Guacamole 是一个无客户端远程桌面网关.它支持标准协议, ...

  8. springboot整合springsecurity安全框架(后端spring_security模块代码可直接使用,根据需求自定义修改)

    SpringSecurity简介 最下面有与springboot整合的模块代码 用户认证和用户授权 主要包含两部分:用户认证和用户授权 用户认证:进入用户登录时候,输入用户名密码,查询数据库查看是否正 ...

  9. Springboot整合Dubbo简单示例

    Springboot 整合dubbo: 1 简介 Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的 ...

最新文章

  1. python基础代码-python基础,python基础代码大全
  2. 哈工大威海c语言实验报告 第八章 无法运行程序,哈工大威海c语言实验报告.doc...
  3. 条码软件调用ERP系统
  4. 发年终奖了,送台MacBook Air!
  5. sender分析之Selector
  6. mysql 添加删除权限_MySQL实例讲解:添加账户、授予权限、删除用户
  7. spring 的延迟加载
  8. JAVA语法——n的阶乘(高级)
  9. windows 系统快捷键小技巧
  10. 全国大学生大数据技能竞赛比赛心得以及相关资料
  11. ET城市大脑发布“天擎”系统:处理16小时视频仅用1分钟
  12. 在苹果手机上实现虹膜识别(通过改装实现)
  13. 阿里api网关接口客户端demo,java实现源码,其他语言可参考
  14. python程序员收入-令人羡慕!33岁程序员晒出收入和待遇,网友望尘莫及
  15. 计算机网络的时间,计算机网络时间同步技术原理介绍
  16. linux终端软件mobaxterm,连接centos
  17. 条码软件如何添加图片
  18. AES密钥编排Python实现
  19. 爱立信、高通和韩国SK电讯宣布将合作开展5G NR测试
  20. PTA 7-4 分钟秒钟的时间相减

热门文章

  1. vivoiqoo系统会加入鸿蒙吗,iqoo系统和vivo系统不一样 iqoo系统和vivo有什么区别 - 云骑士一键重装系统...
  2. 浅谈计算机数据库技术的应用,浅谈计算机数据库技术的应用意义.doc
  3. java成长道路必备技能
  4. Jquery电话号码的验证
  5. elasticsearch 占CPU过高
  6. 白皮书下载|新一代金融全栈信创云解决方案及成功案例
  7. 【干货】Chrome插件扩展开发全攻略
  8. 整理了阿里开源的15个开源项目,分享给大家
  9. 一段简单的计算机程序举例,第3讲-最简单的C语言程序举例.docx
  10. 023期计算机开机号,便民工作室提供中国福彩开机号023期开机号