流程引擎基础知识

news2025/6/19 20:39:54

流程引擎基础知识

    • 流程部署
    • 流程取消部署
    • 流程发起
    • 流程取回
    • 流程作废
    • 流程委托
    • 流程流转
    • 常用流程表介绍
    • 备注

流程部署

1.后台直接导入bpmn

        /*
         *流程部署源代码
         */
   public void deploy() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.createDeployment().addClasspathResource("test.bpmn").name("谁家女儿郎").deploy();
    }

2.前端画模型

       /**
	 * 创建模型
	 */
	@RequestMapping("/create")
	public Result<String> create(@RequestBody ModelDTO dto, HttpServletRequest request, HttpServletResponse response) {
		Result<String> result = new Result<String>();
		try {
			String modelId = actModelService.save(dto.getName(), dto.getKey(), dto.getDescription());
			result.setResult(modelId);
		    //response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelId);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("新建流程失败!");
		}
		return result;
	}

   public String save(String name, String key, String description) throws UnsupportedEncodingException {
        //新建一个空模型
        Model model = repositoryService.newModel();

        //metaInfo信息
        ObjectNode metaInfo = objectMapper.createObjectNode();
        metaInfo.put(ModelDataJsonConstants.MODEL_NAME, name);
        metaInfo.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        metaInfo.put(ModelDataJsonConstants.MODEL_REVISION, model.getVersion());

        model.setKey(key);
        model.setName(name);
        model.setMetaInfo(metaInfo.toString());

        repositoryService.saveModel(model);

        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilset = objectMapper.createObjectNode();
        stencilset.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.set("stencilset", stencilset);
        repositoryService.addModelEditorSource(model.getId(), editorNode.toString().getBytes("utf-8"));
        return model.getId();
    }

	/**
	 * 流程部署
	 * @param id
	 * @return
	 */
	@GetMapping("deploy/{id}")
	public Result deploy(@PathVariable("id") String id) {
		actModelService.deploy(id);
		return Result.OK("流程发布成功");
	}


    public void deploy(String id) {
        try {
            Model model = repositoryService.getModel(id);
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
            BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
            BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
            byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);

            String processName = model.getName();
            if (!StringUtils.endsWith(processName, ".bpmn20.xml")){
                processName += ".bpmn20.xml";
            }

            ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
            Deployment deployment = repositoryService.createDeployment().name(model.getName()).addInputStream(processName, in).deploy();

            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
            if (list.size() == 0){
                throw new JeecgBootException("流程定义为空");
            }
        } catch (Exception e) {
            throw new JeecgBootException(e);
        }
    }

流程取消部署

1.后台直接导入bpmn

    @GetMapping("/caceldeploy")
    @ApiOperation(notes = "取消部署", value = "取消部署")
    public void caceldeploy(String deployId) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.deleteDeployment(deployId, true);
    }

2.前端画模型

/**
	 * 删除流程设计模型
	 * @param ids
	 * @return
	 */
	@GetMapping(value = "/delete")
	public Result delete(@RequestParam(name = "ids", required = true) String ids) {
		if(CommonRandomUtil.isNotEmpty(ids)) {
			for (String id : Arrays.asList(ids.split(","))) {
				actModelService.delete(id);   //直接删除流程设计模型
			}
		}
		return Result.OK("流程删除成功");
	}

//备注:需实现repositoryService的void deleteDeployment(String deploymentId)的接口

流程发起

1.启动流程,后台导入bpmn

   @GetMapping("/startProcessInstanceByKey")
    @ApiOperation(notes = "创建流程实例", value = "创建流程实例")
    public Result<?> startProcessInstanceByKey(String processDefinitionKey, String businessKey, String initiator) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "deng");
        map.put("reason", "等天黑");
        //设置流程发起人
        identityService.setAuthenticatedUserId("deng");
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, map);
        return Result.OK("等天黑");

    }

2.流程改造后的启动流程

	/**
	 * 启动流程
	 * @param userId
	 * @param businessKey
	 * @param variables
	 * @param extActProcessForm
	 * @return
	 * @throws BpmException
	 */
	private ProcessInstance startWorkflow(String userId, String businessKey, Map<String, Object> variables, ExtActProcessForm extActProcessForm) throws BpmException{
		// 设置流程发起人
		identityService.setAuthenticatedUserId(userId);
		variables.put(WorkFlowGlobals.BPM_FORM_BUSINESSKEY, businessKey);
		variables.put(WorkFlowGlobals.BPM_FORM_TYPE, extActProcessForm.getFormType());
		variables.put(WorkFlowGlobals.BPM_BIZ_TITLE, BpmUtil.getContent(variables,extActProcessForm.getTitleExp()));
		variables.put(WorkFlowGlobals.BPM_PROC_DEAL_STYLE, ProcDealStyleEnum.toEnum(extActProcessForm.getFormDealStyle()).getCode());
		//根据流程id查询流程信息
		ExtActProcess extActProcess = extActProcessMapper.selectById(extActProcessForm.getProcessId());
		
		//获取最新发布的流程定义-----------------核心代码1
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(extActProcess.getProcessKey()).latestVersion().singleResult();
		//update-begin--Author:zhoujf  Date:20180727 for:流程未发布流程提交异常处理
		if(processDefinition==null){
			throw new BpmException("流程未发布,请先发布流程!");
		}
		String formUrl = (String)variables.get(WorkFlowGlobals.BPM_FORM_CONTENT_URL);
		String formUrlM = (String)variables.get(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE);
		formUrl = BpmUtil.getNodeUrl(variables, formUrl, businessKey);
		formUrlM = BpmUtil.getNodeUrl(variables, formUrlM, businessKey);
		variables.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL, formUrl);
		variables.put(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE, formUrlM);

		//根据流程id和部署id查询流程部署节点
//		List<ExtActProcessNodeDeployment> nodeList = new ArrayList<ExtActProcessNodeDeployment>();
//		LambdaQueryWrapper<ExtActProcessNodeDeployment> queryWrapper = new LambdaQueryWrapper<ExtActProcessNodeDeployment>();
//		queryWrapper.eq(ExtActProcessNodeDeployment::getProcessId, extActProcessForm.getProcessId());
//		queryWrapper.eq(ExtActProcessNodeDeployment::getDeploymentId, processDefinition.getDeploymentId());
//		nodeList = extActProcessNodeDeploymentService.list(queryWrapper);
//		if(nodeList!=null&&nodeList.size()>0){
//			for(ExtActProcessNodeDeployment node:nodeList){
//				if(oConvertUtils.isNotEmpty(node.getModelAndView())){
//					variables.put(node.getProcessNodeCode()+":"+WorkFlowGlobals.SUFFIX_BPM_FORM_URL, node.getModelAndView());
//				}
//				if(oConvertUtils.isNotEmpty(node.getModelAndViewMobile())){
//					variables.put(node.getProcessNodeCode()+":"+WorkFlowGlobals.SUFFIX_BPM_FORM_URL_MOBILE, node.getModelAndViewMobile());
//				}
//			}
//		}

         //创建流程实例------------------------------------------------核心代码2
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(extActProcess.getProcessKey(), businessKey, variables);
		if(processInstance==null||oConvertUtils.isEmpty(processInstance.getProcessInstanceId())){
			return null;
		}
		//将流程实例ID存在流程变量里面 ----------------------------------核心代码3
		runtimeService.setVariable(processInstance.getProcessInstanceId(), WorkFlowGlobals.JG_LOCAL_PROCESS_ID, processInstance.getProcessInstanceId());
		return processInstance;
	}

流程取回

/**
	 * 我发起的流程,流程追回按钮,流程取回
	 * 流程追回:删除流程实例,启动表单单据保留,
	 *
	 * @param
	 * @return
	 */
	@PostMapping(value = "/callBackProcess")
	public Result<Map<String, Object>> callBackProcess(@RequestBody HashMap<String, String> map,
													   HttpServletRequest request) {
		Result<Map<String, Object>> result = new Result<Map<String, Object>>();
		try {
			//添加评定业务流程取回时重置表数据功能
			String processInstanceId1 = map.get("processInstanceId");
			//Map<String, Object> flowDataByProcInstId = extActFlowDataService.getFlowDataByProcInstId(processInstanceId1);
			//extActFlowDataService.updateFormDataById((String) flowDataByProcInstId.get("formDataId"));

			String processInstanceId = oConvertUtils.getString(map.get("processInstanceId"));
			ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
			runtimeService.setVariable(pi.getProcessInstanceId(), WorkFlowGlobals.BPM_STATUS, WorkFlowGlobals.PROCESS_CALLBACKPROCESS_STATUS);
			runtimeService.deleteProcessInstance(processInstanceId, "发起人流程追回");
			result.success("追回成功");
		} catch (Exception e) {
			e.printStackTrace();
			result.error500("追回失败");
		}
		return result;
	}

流程作废

	/**
	 * 我发起的流程,作废按钮
	 *
	 * @param
	 * @return
	 */
	@PostMapping(value = "/invalidProcess")
	public Result<Map<String, Object>> invalidProcess(@RequestBody HashMap<String, String> map,
													  HttpServletRequest request) {
		Result<Map<String, Object>> result = new Result<Map<String, Object>>();
		try {
			String processInstanceId = oConvertUtils.getString(map.get("processInstanceId"));
			ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
			runtimeService.setVariable(pi.getProcessInstanceId(), WorkFlowGlobals.BPM_STATUS, WorkFlowGlobals.PROCESS_INVALIDPROCESS_STATUS);
			runtimeService.deleteProcessInstance(processInstanceId, "发起人流程作废");
			result.success("作废成功");
		} catch (Exception e) {
			e.printStackTrace();
			result.error500("作废失败");
		}
		return result;
	}

流程委托

/**
	 * 委托
	 *
	 * @param
	 * @return
	 */
	@PostMapping(value = "/taskEntrust111")
	public Result<Map<String, Object>> taskEntrust111(@RequestBody HashMap<String, String> map,
													  HttpServletRequest request) {
		Result<Map<String, Object>> result = new Result<Map<String, Object>>();
		try {
			String taskId = oConvertUtils.getString(map.get("taskId"));
			//委托要改成批量委托taskId用逗号分隔
			List<String> list = Arrays.asList(taskId.split(","));
			for (String s : list) {
				String taskAssignee = oConvertUtils.getString(map.get("taskAssignee"));
				Task task = taskService.createTaskQuery().taskId(s).active().singleResult();
				//判断任务是否签收没有签收需要进行签收
				if (oConvertUtils.isEmpty(task.getAssignee())) {
					String userId = JwtUtil.getUserNameByToken(request);
					taskService.claim(s, userId);
				}
				taskService.delegateTask(task.getId(), taskAssignee);
			}
			result.success("委托成功");
		} catch (Exception e) {
			e.printStackTrace();
			result.error500("委托失败");
		}
		return result;
	}

流程流转

/**
	 * 提交流程处理
	 *
	 * @param map
	 * @param request
	 * @return
	 */
	@PostMapping(value = "processComplete")
	public Result<Object> processComplete(@RequestBody HashMap<String, String> map,
										  HttpServletRequest request) {
		Long startTime = System.currentTimeMillis();
		log.debug("进入方法processComplete内,当前时间戳{}" + startTime);
		Result<Object> result = new Result<Object>();
		try {
			//监听通过request取到参数的信息的处理
			request.setAttribute("data", map);
			String taskId = oConvertUtils.getString(map.get("taskId"));
			//下一节点名称
			String nextnode = oConvertUtils.getString(map.get("nextnode"));
			//下一步节点的数目(小心歧义)
			Integer nextCodeCount = oConvertUtils.getInt(map.get("nextCodeCount"));
//		String way = oConvertUtils.getString(request.getParameter("way"));
//		ProcessHandle processHandle = activitiService.getProcessHandle(taskId);
			//模式类型(单/多分支模式/驳回模式)
			String model = oConvertUtils.getString(map.get("processModel"));
			//下一步操作人
			String nextUser = oConvertUtils.getString(map.get("nextUserId"));
			//驳回时选择驳回到哪一节点
			String rejectNode = oConvertUtils.getString(map.get("rejectModelNode"));

			String accomplishFlag = "";
			if (map.get("accomplishFlag") != null) {
				accomplishFlag = oConvertUtils.getString(map.get("accomplishFlag"));
			}


			//TODO 流程变量参数
//		Map<String, Object> varmap = var.getVariableMap(processHandle.getTpProcesspros());
			Map<String, Object> varmap = new HashMap<String, Object>();
			Task task = activitiService.getTask(taskId);
			if (task == null) {
				return Result.error("该节点为首节点,无法驳回");
			}
			String processInstanceId = task.getProcessInstanceId();
			runtimeService.setVariable(processInstanceId, WorkFlowGlobals.BPM_STATUS, WorkFlowGlobals.BPM_BUS_STATUS_2);
			runtimeService.setVariable(processInstanceId, "tenantId", request.getHeader("tenant_id"));
			List<String> nextUserList = Arrays.asList(nextUser.split(","));
			if (nextUserList != null && nextUserList.size() > 0) {
				runtimeService.setVariable(processInstanceId, "nextUser", nextUserList.get(0));
			}

			if (!"1".equals(model) && !"2".equals(model)) {
				// 取得所有历史任务按时间降序排序
				List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
						.processInstanceId(processInstanceId)
						.orderByTaskCreateTime()
						.desc()
						.list();
				//查出离现在第二近的上一节点处理人
				String assignee = "";
				int i = 0;
				for (HistoricTaskInstance historicTaskInstance : htiList) {
					if (historicTaskInstance.getTaskDefinitionKey().equals(rejectNode)) {
						assignee = historicTaskInstance.getAssignee();
						i++;
						if (i == 2) {
							break;
						}
					}
				}
				runtimeService.setVariable(processInstanceId, "rejectNextBy", assignee);
			}
			boolean bflag = this.checkUserTaskIsHuiQian(taskId, nextnode);

			if (bflag) {
				varmap.put(WorkFlowGlobals.ASSIGNEE_USER_ID_LIST, nextUser);
				runtimeService.setVariable(processInstanceId, WorkFlowGlobals.ASSIGNEE_USER_ID_LIST, nextUser);
				if (!"".equals(accomplishFlag)) {
					varmap.put("accomplish_flag", accomplishFlag);
				}
			}
			//判断是否是委托任务,被委托人先解决委托
			if (StringUtils.isNotBlank(task.getOwner())) {
				DelegationState delegationState = task.getDelegationState();
				switch (delegationState) {
					case PENDING:
						taskService.resolveTask(taskId);
						break;
					case RESOLVED:
						//委托任务已经完成
						break;

					default:
						//不是委托任务
						break;
				}
			}

			String rejectDescription = "";
			if ("1".equals(model)) {
				//---update-begin-----autor:zhoujf------date:20190927-------for:并行网关停滞不前问题--------
				//判断是否是并行网关
				boolean isParallelGateway = this.checkParallelGateway(task.getProcessDefinitionId(), nextnode);
				//单分支模式
				if ("end".equals(nextnode)) {
					if (nextCodeCount == 1 || isParallelGateway) {
						taskService.complete(taskId, varmap);
					} else {
						activitiService.goProcessTaskNode(taskId, nextnode, varmap);
					}
				} else {
					//多分支模式
					if (nextCodeCount == 1 || isParallelGateway) {
						taskService.complete(taskId, varmap);
					} else {
						activitiService.goProcessTaskNode(taskId, nextnode, varmap);
					}
					//---update-end-----autor:zhoujf------date:20190927-------for:并行网关停滞不前问题--------
					//如果下个节点不是会签节点,动态指派下一步处理人
					if (!bflag) {
						//会签情况下,该SQL会报错
						String nextTskId = activitiService.getTaskIdByProins(processInstanceId, nextnode);
						//---update-begin-----autor:scott------date:20190925-------for:TASK #3188 下一步节点不是任务节点的情况下,不走指派逻辑不然报错。比如:下一步是个网关--------
						if (oConvertUtils.isNotEmpty(nextUser) && oConvertUtils.isNotEmpty(nextTskId)) {
							//---update-end-----autor:scott------date:20190925-------for:TASK #3188 下一步节点不是任务节点的情况下,不走指派逻辑不然报错。比如:下一步是个网关--------
							if (nextUser.indexOf(",") < 0) {
								//指定单个执行人
								taskService.setAssignee(nextTskId, nextUser);
							} else {
								//---update-begin-----autor:scott------date:20190925-------for:TASK #3187 【疑似BUG】 出差申请 下一步操作人 选择多个
								//指定多人
								taskService.setAssignee(nextTskId, null);
								for (String userid : nextUser.split(",")) {
									if (oConvertUtils.isNotEmpty(userid)) {
										taskService.addCandidateUser(nextTskId, userid);
									}
								}
								//---update-end-----autor:scott------date:20190925-------for:TASK #3187 【疑似BUG】 出差申请 下一步操作人 选择多个
							}
						}
					} else {
						runtimeService.setVariable(processInstanceId, "assigneeUserIdList", nextUser);
					}
				}
			} else if ("2".equals(model)) {
				//多分支模式
				taskService.complete(taskId, varmap);
			} else {
				runtimeService.setVariable(processInstanceId, WorkFlowGlobals.BPM_STATUS, WorkFlowGlobals.PROCESS_REJECTPROCESS_STATUS);
				//驳回模式
				activitiService.goProcessTaskNode(taskId, rejectNode, varmap);
				String nextTskId = activitiService.getTaskIdByProins(processInstanceId, rejectNode);
				// 取得所有历史任务按时间降序排序
				List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
						.processInstanceId(processInstanceId)
						.orderByTaskCreateTime()
						.desc()
						.list();
				//查出离现在第二近的上一节点处理人
				String assignee = "";
				int i = 0;
				for (HistoricTaskInstance historicTaskInstance : htiList) {
					if (historicTaskInstance.getTaskDefinitionKey().equals(rejectNode)) {
						assignee = historicTaskInstance.getAssignee();
						i++;
						if (i == 2) {
							break;
						}
					}
				}
//				runtimeService.setVariable(processInstanceId,"rejectNextBy",assignee);
				//TODO  这行代码替换了下面注释的部分
				try {
					taskService.setAssignee(nextTskId, assignee);
				} catch (ActivitiIllegalArgumentException e) {
					log.info("taskId is null");
				}

//				if(oConvertUtils.isNotEmpty(nextUser)){
//					if(nextUser.indexOf(",") < 0){
//						//指定单个执行人
//						taskService.setAssignee(nextTskId,nextUser);
//					}else{
//						//指定多人
//						taskService.setAssignee(nextTskId,null);
//						//---update-begin-----autor:scott------date:20190930------for:TASK #3187 【疑似BUG】 出差申请 下一步操作人 选择多个
//						for (String userid : nextUser.split(",")) {
//							if (oConvertUtils.isNotEmpty(userid)) {
//								taskService.addCandidateUser(nextTskId, userid);
//							}
//						}
//						//---update-end-----autor:scott------date:20190930-------for:TASK #3187 【疑似BUG】 出差申请 下一步操作人 选择多个
//					}
//				}

				//TODO  流程委托、驳回 日志问题
				Task nexttask = activitiService.getTask(nextTskId);
				//---update-begin-----autor:scott------date:20191203------for:驳回人显示真实名字,不显示账号
				String assigneeUserName = task.getAssignee();
				LoginUser loginUser = sysBaseAPI.getUserByName(task.getAssignee());
				if (loginUser != null) {
					assigneeUserName = loginUser.getRealname();
				}
				//---update-end-----autor:scott------date:20191203------for:驳回人显示真实名字,不显示账号

				rejectDescription = assigneeUserName + "驳回任务 〔" + task.getName() + "〕 →〔" + nexttask.getName() + "〕 ";
//				List<HistoricTaskInstance>  hiTaskInstList = historyService.createHistoricTaskInstanceQuery().taskId(taskId).list();
//				ActHiTaskinst actHiTaskinst = this.systemService.get(ActHiTaskinst.class, taskId);
//				actHiTaskinst.setDescription(rejectDescription);
//				actHiTaskinst.setDeleteReason(rejectDescription);
//				this.systemService.saveOrUpdate(actHiTaskinst);
				// 流程委托、驳回 日志问题
			}

			String username = JwtUtil.getUserNameByToken(request);
			LoginUser user = sysBaseAPI.getUserByName(username);
			// 任务抄送处理
			String ccUserNames = oConvertUtils.getString(map.get("ccUserIds"));
			//任务抄送记录
			taskCc(ccUserNames, task, username);

			//每个task节点执行完成后,处理审批日志
			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();

			String reason = oConvertUtils.getString(map.get("reason"));
			ExtActBpmLog bpmlog = new ExtActBpmLog();
			if (processInstance != null) {
				bpmlog.setBusinessKey(processInstance.getBusinessKey());
				bpmlog.setProcName(processInstance.getName());
			}
//			bpmlog.setOpStatus(opStatus);
			bpmlog.setOpTime(new Date());
//			bpmlog.setOpType(WorkFlowGlobals.BPM_OP_TYPE_1);
			bpmlog.setOpUserId(username);
			if (user != null) {
				bpmlog.setOpUserName(user.getRealname());
			}
			bpmlog.setProcInstId(processInstanceId);
			if (oConvertUtils.isNotEmpty(rejectDescription)) {
				reason = reason + "       『 " + rejectDescription + " 』";
			}
			bpmlog.setRemarks(reason);
			bpmlog.setTaskDefKey(task.getTaskDefinitionKey());
			bpmlog.setTaskId(taskId);
			bpmlog.setTaskName(task.getName());
			extActBpmLogService.save(bpmlog);
			//保存附件
			String fileList = oConvertUtils.getString(map.get("fileList"));
			saveBpmFiles(bpmlog.getId(), fileList);
		} catch (BpmException e) {
			result.error500("任务执行失败:" + e.getMessage());
			e.printStackTrace();
		} catch (ActivitiException e) {
			result.error500("任务执行失败:" + e.getMessage());
			e.printStackTrace();
			Object actObj = e.getCause();
			if (actObj != null) {
				Throwable throwable = (Throwable) actObj;
				if (throwable.getCause() != null && throwable.getCause() instanceof BpmException) {
					result.error500("任务执行失败:" + throwable.getCause().getMessage());
				}
			}
		} catch (Exception e) {
			result.error500("任务执行失败:" + e.getMessage());
			e.printStackTrace();
			Object actObj = e.getCause();
			if (actObj != null) {
				Throwable throwable = (Throwable) actObj;
				if (throwable.getCause() != null && throwable.getCause() instanceof BpmException) {
					result.error500("任务执行失败:" + throwable.getCause().getMessage());
				}
			}
		}
		Long endTime = System.currentTimeMillis();
		log.debug("方法processComplete结束前,当前时间戳{}" + endTime);
		log.debug("耗时(毫秒):{}", endTime - startTime);

		return result;
	}

常用流程表介绍

1.历史节点表—act_hi_actinst
流程历史节点表常用来查询流程走过的节点
在这里插入图片描述

2.历史变量表—act_hi_varinst
流程历史节点表常用来查询流程走到的节点的元数据(业务数据)
在这里插入图片描述

3.运行时任务节点表—act_ru_lask
运行时加点表表明当前流程走到的节点

在这里插入图片描述

4.运行时流程变量数据表—act_ru_variable
运行时加点表表明当前流程走到的节点信息(业务数据)
在这里插入图片描述
5.流程部署信息表—act_re_deployment
流程部署后流程存储的地方—主要字段id(流程部署id)
在这里插入图片描述

6.流程定义数据表—act_re_prodef
流程定义
在这里插入图片描述

7.运行时流程人员表—act_ru_identitylink
每个节点的人员信息
在这里插入图片描述

8.运行时流程实例表—act_ru_execution
关键表,集合了流程实例id,流程定义id,流程节点id,以及业务表id
在这里插入图片描述

9.运行各个表之间的关系
表之间的关系以及字段

备注

流程实例id贯穿运行表,运行表业务字段,历史表,历史表业务字段,流程实例表,属于比较重要的字段

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/411590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用ChatGPT在1天内完成毕业论文

如何使用ChatGPT在1天内完成毕业论文 几天前&#xff0c;亲眼见证了到一位同学花了1天时间用ChatGPT完成了他的毕业论文&#xff0c;世道要变&#xff0c;要学会使用黑科技才能混的下去。废话到此结束&#xff0c;下面说明这么用AI生成自己的论文。 使用工具&#xff1a; 1. P…

Maven(一):什么是Maven?

Maven&#xff08;一&#xff09;&#xff1a;什么是Maven&#xff1f;前言一、为什么要学习Maven&#xff1f;1、Maven 作为依赖管理工具1.1 jar 包的规模1.2 jar 包的来源1.3 jar 包之间的依赖关系2、Maven 作为构建管理工具2.1 你没有注意过的构建2.2 脱离 IDE 环境仍需构建…

【ERNIE Bot】百度 | 文心一言初体验

文章目录一、前言二、文心一言介绍三、申请体验⌈文心一言⌋四、⌈文心一言⌋初体验1️⃣聊天对话能力2️⃣文案创作能力3️⃣文字转语音能力✨4️⃣AI绘画能力✨5️⃣数理推理能力6️⃣代码生成能力7️⃣使用技巧说明五、总结一、前言 ​ 最近有关人工智能的热门话题冲上热榜…

亚马逊云科技十七年持续进化,解锁Amazon S3的七项新发布

17年前的3月14日&#xff0c;亚马逊云科技推出了一项“非常简单的”对象存储服务&#xff08;Amazon Simple Storage Service&#xff09;。该服务允许开发人员创建、列出和删除私有存储空间&#xff08;称为存储桶&#xff09;、上传和下载文件以及管理其访问权限。当时&#…

【C#+Unity小白】制作一款简单的2D平台游戏,PONG(弹球)游戏

素材均来自于Brackeys 各位可以到Youtube支持他&#xff0c;他的视频底下有他个人的网站&#xff0c;各位可以从他拿素材。 像我这样的菜鸡&#xff0c;在我看codeMonkey零零散散的制作视频而不知所措时&#xff0c;Brackeys出现了&#xff0c;他耐心教导&#xff0c;他真的是…

【2023最新】超详细图文保姆级教程:App开发新手入门(1)

1. 关于 『YonBuilder移动开发』 PS: 本段内容主要目的是去除官方语音描述&#xff0c;用通俗的语言来简单介绍一下『YonBuilder移动开发』&#xff0c;方便新手开发者判断是否适合自己上手学习。 简介&#xff1a; YonBuilder移动开发平台(官网&#xff1a;https://develope…

2023年14界蓝桥杯省赛“日期统计”题解

问题描述 小蓝现在有一个长度为 100 的数组&#xff0c;数组中的每个元素的值都在 0 到 9 的范围之内。数组中的元素从左至右如下所示&#xff1a; 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 …

Python 小型项目大全 41~45

四十一、幸运星 原文&#xff1a;http://inventwithpython.com/bigbookpython/project41.html 在这个碰运气游戏中&#xff0c;你掷骰子来收集星星。你掷得越多&#xff0c;你能得到的星星就越多&#xff0c;但是如果你得到三个头骨&#xff0c;你就失去了一切&#xff01;这款…

【网络编程】UDP

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; 目 录&#x1f3ef;一. UDP数据报套接字编程&#x1f3f0;二. 写一个 UDP 版本的 回显服务器-客户端.&#xff08;echo server&#xff09;&#x1f3ed;1. 服务器&#xff1a;&…

咖啡卷到现在,他们开始往里面掺北京豆汁了

咖啡卷到现在&#xff0c;他们开始往里面掺北京豆汁了0. 导读1. 人手一杯&#xff0c;果咖大势所趋2. 双倍成瘾&#xff1a;茶咖和酒咖被重点推荐3. 地方小吃融入咖啡&#xff0c;比如北京豆汁4. 炙手可热的云南咖啡豆5. 咖啡、户外和环保&#xff1a;绑定可持续6. 小结0. 导读…

vue - 【最新】简单快捷的 element ui 组件库的主题色更改,批量统一覆盖替换解决方法,无需npm装包。(适用于新手小白的方法,很简单)

效果图 最新解决方案,简单便捷且不用npm安装任何第三方包就能搞定。 原来的主题色是蓝色 ,可以通过本篇博客提供的方法,统一变成其他主题颜色,比如下面的紫色: 下面就是真实的运行效果,保证可行~ 这样就不用每个组件单独去写样式覆盖颜色了! 定制主

干雾抑尘系统的降尘工作原理

对于干雾抑尘系统&#xff0c;相信大家现在都不陌生&#xff0c;作为工业无组织排放粉尘治理的常用除尘产品&#xff0c;其有着传统喷雾降尘设备无法比拟的优势。今天我们就来了解下&#xff0c;干雾抑尘系统到底是什么&#xff1f;他的工作原理到底是怎样的呢&#xff1f; ​…

进程、线程、协程的区别

目录 1、什么是进程&#xff1f; 2、什么是线程&#xff1f; 3、什么是协程&#xff1f; 4、进程、线程、协程的区别 (1) 进程、线程的区别 (2) 线程、协程的区别 1、什么是进程&#xff1f; 简单来说&#xff0c;进程可以看做是加载到内存里的程序&#xff0c;实际上一…

Qt Quick - ColorDialog 颜色对话框

ColorDialog 颜色对话框使用总结一、概述二、实现的要点三、一些例子的合集1. 按钮点击修改按钮文字颜色一、概述 ColorDialog 就是Qt 提供的标准的颜色对话框。ColorDialog 允许用户选择颜色。 对话框最初是不可见的。你需要首先按需设置属性&#xff0c;然后将visible设置为…

前端 icon 方案该升级了

说到 icon&#xff0c;很多前端开发只能想到 iconfont&#xff0c;或者组件库中提供的那些图标&#xff0c;当然这对于绝大多数开发场景是够用的。 但要知道&#xff0c;iconfont 的方案其实是在 2016 年公开&#xff0c;到现在也已经有 6 年之久&#xff0c;它确实在这一段时…

【产品经理】为什么你画的流程图开发总说看不懂?

在做产品设计时&#xff0c;会碰到非常多的业务流程&#xff0c;当我们需要跟开发解释一个相对复杂的流程时&#xff0c;一个清晰的流程图&#xff0c;便非常重要了。 我们做产品设计的时候&#xff0c;会碰到非常多的业务流程&#xff0c;有简单的&#xff0c;有复杂的&#x…

「业务架构」需求工程——捕获与分析(第二部分)

从用户、客户和其他涉众那里生成系统需求的活动。可行性研究结束后&#xff0c;我们进入下一个阶段;抽取和分析。需求捕获和分析它是一个与客户和最终用户交互的过程&#xff0c;以查明领域需求、系统应该提供什么服务以及其他约束。领域需求反映了系统运行的环境&#xff0c;因…

HTML5 <del> 标签、HTML5 <dd> 标签

HTML5 <del> 标签 实例 一段带有已删除部分和新插入部分的文本&#xff1a; <p>My favorite color is <del>blue</del> <ins>red</ins>!</p> 尝试一下 浏览器支持 所有主流浏览器都支持 <del> 标签。 标签定义及使用说明 …

什么是设计模式?

文章目录01 | 概念02 | 要素03 | 分类04 | 总结“每一个模式描述了一个在我们周围不断重复发生的问题&#xff0c;以及问题的解决方案的核心。这样&#xff0c;你就能一次又一次地使用该方案而不必做重复劳动”。 设计模式的核心&#xff1a;提供了相关问题的解决方案&#xff…

机械硬盘提示格式化的常见原因|3种数据恢复方法

机械硬盘是电脑存储设备中的一种&#xff0c;它的存储容量比较大&#xff0c;通常采用机械运动的方式记录数据。 其内部结构由多个盘片和磁头组成&#xff0c;盘片层层叠放在一起并通过主轴转动&#xff0c;磁头则通过磁臂上下移动并接触盘片表面进行读写操作。但是在日常使用电…