静态解析activiti文本,不入库操作流程
说明:
activiti本身状态存库,导致效率太低,把中间状态封装成一个载荷类,返回给上游,下次请求时给带着载荷类即可。
1.pom依赖
<dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>${json-lib.version}</version><classifier>jdk15</classifier></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-engine</artifactId><version>5.22.0</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-bpmn-converter</artifactId><version>5.22.0</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-bpmn-model</artifactId><version>5.22.0</version></dependency>
2.关键类
2.1解析类-BPMNService
package cn.com.agree.activiti10;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.CallActivity;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.InclusiveGateway;
import org.activiti.bpmn.model.ParallelGateway;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.engine.impl.util.io.InputStreamSource;
import org.mvel2.MVEL;import log.cn.com.agree.ab.a5.runtime.InvokeLog;import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
/*** 静态解析bpmn文件 -返回payLoad* payLoad:包含相关信息,替代数据库中 存储的信息。比如当前交易名,对象组名,整体链路节点等* 每次请求时带着payLoad* @author fanjinliang@agree.com.cn**/
public class BPMNService {private Map<String, BpmnModel> bpmnModelMap = new HashMap<>();private Map<String, Process> processMap = new HashMap<>();// 初始化方法,在服务启动时调用public void init(List<String> bpmnFilePaths) throws Exception {for (String filePath : bpmnFilePaths) {loadBpmnModel(filePath);}}// 加载单个 BPMN 文件private void loadBpmnModel(String bpmnFilePath) throws Exception {InputStream bpmnStream = new FileInputStream(bpmnFilePath);BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();InputStreamSource inputStreamSource = new InputStreamSource(bpmnStream);BpmnModel bpmnModel = bpmnXMLConverter.convertToBpmnModel(inputStreamSource, false, false);bpmnStream.close();for (Process process : bpmnModel.getProcesses()) {String definitionKey = process.getId();bpmnModelMap.put(definitionKey, bpmnModel);processMap.put(definitionKey, process);}}// 根据 definitionKey 获取 Processpublic Process getProcessByDefinitionKey(String definitionKey) {return processMap.get(definitionKey);}// 根据当前节点的 ID 获取下一个节点(包括处理网关和嵌套流程)public FlowElement getNextFlowElement(String definitionKey, String currentElementId, Map<String, Object> variables) throws ActivitiException{Process process = getProcessByDefinitionKey(definitionKey);if (process == null||process.getFlowElement(currentElementId)==null) {return null;}FlowElement currentElement = process.getFlowElement(currentElementId);FlowElement flowElement =null;if (currentElement instanceof FlowNode) {List<SequenceFlow> outgoingFlows = ((FlowNode) currentElement).getOutgoingFlows();if (outgoingFlows.isEmpty()) {return null;}Class<?> currentElementType = currentElement.getClass();switch (currentElementType.getSimpleName()) {case "ExclusiveGateway":// 处理排他网关for (SequenceFlow outgoingFlow : outgoingFlows) {if (evaluateCondition(outgoingFlow.getConditionExpression(), variables)) {return process.getFlowElement(outgoingFlow.getTargetRef());}}
// InvokeLog.error("网关不匹配");throw new ActivitiException(ActivitiServiceResults.BIZ002_网关未匹配);
// break;case "ParallelGateway":case "InclusiveGateway":// 处理并行网关或包容网关,假设返回第一个符合条件的目标节点for (SequenceFlow outgoingFlow : outgoingFlows) {return process.getFlowElement(outgoingFlow.getTargetRef());}break;case "CallActivity":// 处理 CallActivityString calledElement = ((CallActivity) currentElement).getCalledElement();Process calledProcess = getProcessByDefinitionKey(calledElement);if (calledProcess != null) {// 假设子流程的开始事件是唯一的for (FlowElement element : calledProcess.getFlowElements()) {if (element instanceof StartEvent) {return element;}}}break;case "SubProcess":// 处理 SubProcessflowElement = process.getFlowElement(outgoingFlows.get(0).getTargetRef());break;default:// 默认处理,返回第一个目标节点flowElement = process.getFlowElement(outgoingFlows.get(0).getTargetRef());break;}// if (currentElement instanceof ExclusiveGateway) {// // 处理排他网关// for (SequenceFlow outgoingFlow : outgoingFlows) {// if (evaluateCondition(outgoingFlow.getConditionExpression(), variables)) {// return process.getFlowElement(outgoingFlow.getTargetRef());// }else {// throw new RuntimeException("网关不匹配");// }// }// } else if (currentElement instanceof ParallelGateway || currentElement instanceof InclusiveGateway) {// // 处理并行网关或包容网关,假设返回第一个符合条件的目标节点// for (SequenceFlow outgoingFlow : outgoingFlows) {// return process.getFlowElement(outgoingFlow.getTargetRef());// }// } else if (currentElement instanceof CallActivity) {// // 处理 callActivity// String calledElement = ((CallActivity) currentElement).getCalledElement();// Process calledProcess = getProcessByDefinitionKey(calledElement);// if (calledProcess != null) {// // 假设子流程的开始事件是唯一的// for (FlowElement element : calledProcess.getFlowElements()) {// if (element instanceof StartEvent) {// return element;// }// }// }// } else if (currentElement instanceof SubProcess) {// // 处理 SubProcess// flowElement =process.getFlowElement(outgoingFlows.get(0).getTargetRef());// } // else {// flowElement = process.getFlowElement(outgoingFlows.get(0).getTargetRef());// // 默认处理,返回第一个目标节点// }}//判断flowElement的类型if (flowElement!=null) {//对象组后的汇总网关放过就行if (currentElement instanceof SubProcess&&flowElement instanceof ParallelGateway) {flowElement=getNextFlowElement(process, flowElement.getId(), variables);}}return flowElement;}private boolean evaluateCondition(String conditionExpression, Map<String, Object> variables) {if (conditionExpression == null || conditionExpression.trim().isEmpty()) {return true; // 无条件表达式时默认返回 true}return MVEL.evalToBoolean(conditionExpression.replaceAll("\\$|\\{|\\}", ""), variables);}public ProcessPayload startProcess(String definitionKey, Map<String, Object> var) throws ActivitiException {// TODO Auto-generated method stubProcess process = processMap.get(definitionKey);if (process==null) {throw new ActivitiException(ActivitiServiceResults.BIZ001_流程定义不存在);}Collection<FlowElement> flowElements = process.getFlowElements();String startId="";for (FlowElement e : flowElements) {if (e instanceof StartEvent) {startId = e.getId();break;}}FlowElement nextFlowElement = getNextFlowElement(definitionKey, startId, var);ProcessPayload processPayload=new ProcessPayload(definitionKey, process.getName());refreshProcessPayload(processPayload,nextFlowElement);return processPayload;}private void refreshProcessPayload(ProcessPayload processPayload, FlowElement nextFlowElement) {// TODO Auto-generated method stubif (nextFlowElement==null) {processPayload.setEnd(true);return;}String id=nextFlowElement.getId();String name=nextFlowElement.getName();String type = nextFlowElement.getClass().getSimpleName();SimpleFlowElement simpleFlowElement = new SimpleFlowElement(id, name, type);Set<String> objIds=new HashSet<String>();if ("SubProcess".equalsIgnoreCase(type)) {//对象组simpleFlowElement.setSubProcess(true);SubProcess sub=(SubProcess)nextFlowElement;List<SimpleFlowElement> subSimpleFlowElement=getSubProcessSimpleFlowElement(sub);//更新当前对象组的对象列表simpleFlowElement.setSubSimpleFlowElement(subSimpleFlowElement);for (SimpleFlowElement e : subSimpleFlowElement) {objIds.add(e.getId());}//更新当前对象组的对象id列表}else if ("ExclusiveGateway".equalsIgnoreCase(type)) {simpleFlowElement.setExclusiveGateway(true);objIds.add(simpleFlowElement.getId());}else if ("ParallelGateway".equalsIgnoreCase(type)) {simpleFlowElement.setParallelGateway(true);objIds.add(simpleFlowElement.getId());}else {objIds.add(simpleFlowElement.getId());}processPayload.setCurrentObjtIdSet(objIds);processPayload.setCurrentFlowElement(simpleFlowElement);}/*** 获取对象组内的对象节点信息* @param process* @return*/private List<SimpleFlowElement> getSubProcessSimpleFlowElement(SubProcess process) {// TODO Auto-generated method stubList<SimpleFlowElement> list=new ArrayList<SimpleFlowElement>();Collection<FlowElement> flowElements = process.getFlowElements();for (FlowElement e : flowElements) {if (!(e instanceof StartEvent || e instanceof EndEvent || e instanceof SequenceFlow)) {String id=e.getId();String name=e.getName();String type = e.getClass().getSimpleName();SimpleFlowElement simpleFlowElement = new SimpleFlowElement(id, name, type);list.add(simpleFlowElement);}}return list;}private FlowElement getNextFlowElement(Process process, String currentElementId, Map<String, Object> var) {if (process == null) {return null;}FlowElement currentElement = process.getFlowElement(currentElementId);if (currentElement == null) {return null;}if (currentElement instanceof FlowNode) {List<SequenceFlow> outgoingFlows = ((FlowNode) currentElement).getOutgoingFlows();if (outgoingFlows.isEmpty()) {return null;}if (currentElement instanceof ExclusiveGateway) {// 处理排他网关for (SequenceFlow outgoingFlow : outgoingFlows) {if (evaluateCondition(outgoingFlow.getConditionExpression(), var)) {return process.getFlowElement(outgoingFlow.getTargetRef());}}} else if (currentElement instanceof ParallelGateway || currentElement instanceof InclusiveGateway) {// 处理并行网关或包容网关,假设返回第一个符合条件的目标节点for (SequenceFlow outgoingFlow : outgoingFlows) {return process.getFlowElement(outgoingFlow.getTargetRef());}} else if (currentElement instanceof CallActivity) {// 处理 callActivityString calledElement = ((CallActivity) currentElement).getCalledElement();Process calledProcess = getProcessByDefinitionKey(calledElement);if (calledProcess != null) {// 假设子流程的开始事件是唯一的for (FlowElement element : calledProcess.getFlowElements()) {if (element instanceof StartEvent) {return element;}}}} else {// 默认处理,返回第一个目标节点return process.getFlowElement(outgoingFlows.get(0).getTargetRef());}}return null;}public ProcessPayload commitProcess(ProcessPayload processPayload, Set<String> commitObjIdSet, Map<String, Object> var) {try {SimpleFlowElement currentFlowElement = processPayload.getCurrentFlowElement();if (currentFlowElement.isSubProcess()) {//处理对象组List<SimpleFlowElement> subSimpleFlowElement = currentFlowElement.getSubSimpleFlowElement();for (String string : commitObjIdSet) {for (SimpleFlowElement e : subSimpleFlowElement) {if (e.getId().equalsIgnoreCase(string)) {e.setCommit(true);processPayload.getCurrentObjtIdSet().remove(string);currentFlowElement.getFlowElementNum().addAndGet(1);}}}// if (currentFlowElement.getFlowElementNum().get()==subSimpleFlowElement.size()) {// //当前对象组提交完毕// // }if (processPayload.getCurrentObjtIdSet().size()==0) {//当前对象组提交完毕//1.更新当前节点状态currentFlowElement.setCommit(true);//2.更新历史节点processPayload.addHistoryFlowElement(currentFlowElement);//3.获取下一节点并且封装对象FlowElement nextFlowElement = getNextFlowElement(processPayload.getId(), currentFlowElement.getId(), var);refreshProcessPayload(processPayload, nextFlowElement);
// return processPayload;}else {//仍然返回当前节点
// return processPayload;}}else {//非对象组currentFlowElement.setCommit(true);//2.更新历史节点processPayload.addHistoryFlowElement(currentFlowElement);//3.获取下一节点并且封装对象FlowElement nextFlowElement = getNextFlowElement(processPayload.getId(), currentFlowElement.getId(), var);refreshProcessPayload(processPayload, nextFlowElement);}} catch (Exception e) {e.printStackTrace();if (e instanceof ActivitiException) {ActivitiException ae=(ActivitiException) e;processPayload.setErrorInfo(ae);}}return processPayload;}}
2.2 自定义节点类-SimpleFlowElement
package cn.com.agree.activiti10;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;public class SimpleFlowElement {private String id;private String name;private String type; // Task, Event, Gateway, etc./* 标识对象是否提交 */private boolean isCommit=false;/* 当前节点是否是对象组 */private boolean isSubProcess;/* 当前节点是否是排他网关 */private boolean isExclusiveGateway;/* 当前节点是否是并行网关 */private boolean isParallelGateway;/* 如果是对象组,保留组内对象 */List<SimpleFlowElement> subSimpleFlowElement=new ArrayList<SimpleFlowElement>();private AtomicInteger flowElementNum=new AtomicInteger(0);public SimpleFlowElement(String id, String name, String type) {this.id = id;this.name = name;this.type = type;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getType() {return type;}public void setType(String type) {this.type = type;}public boolean isCommit() {return isCommit;}public void setCommit(boolean isCommit) {this.isCommit = isCommit;}public boolean isSubProcess() {return isSubProcess;}public void setSubProcess(boolean isSubProcess) {this.isSubProcess = isSubProcess;}public List<SimpleFlowElement> getSubSimpleFlowElement() {return subSimpleFlowElement;}public void setSubSimpleFlowElement(List<SimpleFlowElement> subSimpleFlowElement) {this.subSimpleFlowElement = subSimpleFlowElement;}public boolean isExclusiveGateway() {return isExclusiveGateway;}public void setExclusiveGateway(boolean isExclusiveGateway) {this.isExclusiveGateway = isExclusiveGateway;}public boolean isParallelGateway() {return isParallelGateway;}public void setParallelGateway(boolean isParallelGateway) {this.isParallelGateway = isParallelGateway;}public AtomicInteger getFlowElementNum() {return flowElementNum;}public void setFlowElementNum(AtomicInteger flowElementNum) {this.flowElementNum = flowElementNum;}}
2.3 自定义载荷类
package cn.com.agree.activiti10;import java.util.ArrayList;
import java.util.List;
import java.util.Set;public class ProcessPayload {/* 活动ID */private String id;/* 活动name */private String name;/* 当前节点 */private SimpleFlowElement currentFlowElement;/* 历史节点 */private List<SimpleFlowElement> historyFlowElement=new ArrayList<SimpleFlowElement>();// /* 一级流程下的节点ID ---合并到currentFlowElement*/
// private String currentObjtId;/* 提交上来的taskId */
// private Set<String> commitObjtId;// /* 当前节点是否是对象组 ---合并到currentFlowElement */
// private boolean isSubProcess;// /* 当前待做的taskId,如果是对象组,那就是多个 ---合并到currentFlowElement*/private Set<String> currentObjtIdSet;private boolean end=false;//TODO 接收到json串的时候,记得把上次可能存在的错误信息给重置下private String code="200";private String message;public ProcessPayload() {}public ProcessPayload(String id, String name) {this.id = id;this.name = name;}public ProcessPayload errorProcessPayload(String msg) {this.setCode("400");this.setMessage(msg);return this;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public SimpleFlowElement getCurrentFlowElement() {return currentFlowElement;}public void setCurrentFlowElement(SimpleFlowElement currentFlowElement) {this.currentFlowElement = currentFlowElement;}// public Set<String> getCommitObjtId() {
// return commitObjtId;
// }
//
//
//
// public void setCommitObjtId(Set<String> commitObjtId) {
// this.commitObjtId = commitObjtId;
// }public boolean isEnd() {return end;}public void setEnd(boolean end) {this.end = end;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public List<SimpleFlowElement> getHistoryFlowElement() {return historyFlowElement;}public void setHistoryFlowElement(List<SimpleFlowElement> historyFlowElement) {this.historyFlowElement = historyFlowElement;}public Set<String> getCurrentObjtIdSet() {return currentObjtIdSet;}public void setCurrentObjtIdSet(Set<String> currentObjtIdSet) {this.currentObjtIdSet = currentObjtIdSet;}public void addHistoryFlowElement(SimpleFlowElement historyFlowElement) {getHistoryFlowElement().add(historyFlowElement);}public void setErrorInfo(ActivitiException ae) {this.setCode(ae.getCode());this.setMessage(ae.getMessage());}}
2.4 测试类
package cn.com.agree.activiti10;import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;import org.activiti.bpmn.model.FlowElement;import com.alibaba.fastjson.JSON;public class Test {public static void main(String[] args) {try {BPMNService bpmnService = new BPMNService();// bpmnService.init(Arrays.asList("bpmn\\index.flow.bpmn"));// String definitionKey = "trade/test";// String startNodeId = "task2";bpmnService.init(Arrays.asList("bpmn\\index.activity.bpmn"));String definitionKey = "publicAc";Map<String,Object>var=new HashMap<String,Object>();var.put("a", "2");ProcessPayload processPayload=bpmnService.startProcess(definitionKey,var);String jsonString = JSON.toJSONString(processPayload);System.out.println(jsonString);while (!processPayload.isEnd()) {SimpleFlowElement currentFlowElement = processPayload.getCurrentFlowElement();System.out.println("currentFlowElement ID: " + currentFlowElement.getId());System.out.println("currentFlowElement Name: " + currentFlowElement.getName());System.out.println("currentObjIds : " + processPayload.getCurrentObjtIdSet());System.out.println("=========================================================");Set<String> currentObjtIdSet = processPayload.getCurrentObjtIdSet();Set<String>commitObjIdSet=new HashSet<String>();commitObjIdSet.addAll(currentObjtIdSet);processPayload=bpmnService.commitProcess(processPayload,commitObjIdSet,var);if (!"200".equalsIgnoreCase(processPayload.getCode())) {System.out.println(processPayload.getCode()+"--"+processPayload.getMessage());break;}
// jsonString = JSON.toJSONString(processPayload);
// System.out.println("processPayload"+jsonString);}} catch (Exception e) {e.printStackTrace();}}
}
2.5 其他类
package cn.com.agree.activiti10;public class ActivitiException extends Exception{/*** */private static final long serialVersionUID = 1L;private String code;private String detail;public ActivitiException(ActivitiServiceResults callResult){super(callResult.getMessage());this.code = callResult.getCode();}public ActivitiException(ActivitiServiceResults callResult, String detail){this(callResult);this.detail = detail;}public ActivitiException() {}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}}
package cn.com.agree.activiti10;
public enum ActivitiServiceResults
{BIZ001_流程定义不存在("BIZ001", "流程定义不存在"),BIZ002_网关未匹配("BIZ002", "网关未匹配");private String code;private String message;ActivitiServiceResults(String code, String message){this.code = code;this.message = message;}/*** @return the code*/public String getCode(){return code;}/*** @return the message*/public String getMessage(){return message;}/*** @param code* the code to set*/public void setCode(String code){this.code = code;}/*** @param message* the message to set*/public void setMessage(String message){this.message = message;}
}
2.6 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.activiti.org/test"><process isExecutable="true" id="publicAc" name="通用活动"><startEvent id="startEvent1" name="startEvent" /><endEvent id="endEvent1" name="endEvent" /><userTask id="pubObj_subObject1" name="账务提交处理" objectEntryConditions=""><extensionElements><activiti:formProperty id="CPCP条件" default="" /><activiti:formProperty id="pojoPath" default="BankCModule/scene/activity/publicAc/pubObj/pubObj" /></extensionElements></userTask><parallelGateway id="parallelGateway_subProcess1" name="parallelGateway_风控对象组" /><sequenceFlow id="sequenceFlow_subProcess1" name="" sourceRef="subProcess1" targetRef="parallelGateway_subProcess1" /><subProcess id="subProcess1" name="风控对象组"><startEvent id="subProcess1_start" name="startEvent" /><endEvent id="subProcess_end_authCheck_subObject2" name="endEvent" /><sequenceFlow id="sequenceFlow_start_authCheck_subObject2" name="" sourceRef="subProcess1_start" targetRef="authCheck_subObject2" /><sequenceFlow id="sequenceFlow_end_authCheck_subObject2" name="" sourceRef="authCheck_subObject2" targetRef="subProcess_end_authCheck_subObject2" /><userTask id="authCheck_subObject2" name="授权对象处理" objectEntryConditions=""><documentation>{"id":"subProcess1","name":"风控对象组"}</documentation><extensionElements><activiti:formProperty id="CPCP条件" default="" /><activiti:formProperty id="pojoPath" default="BankCModule/processes/authCheck/authCheck" /></extensionElements></userTask><endEvent id="subProcess_end_reviewCheck_subObject3" name="endEvent" /><sequenceFlow id="sequenceFlow_start_reviewCheck_subObject3" name="" sourceRef="subProcess1_start" targetRef="reviewCheck_subObject3" /><sequenceFlow id="sequenceFlow_end_reviewCheck_subObject3" name="" sourceRef="reviewCheck_subObject3" targetRef="subProcess_end_reviewCheck_subObject3" /><userTask id="reviewCheck_subObject3" name="复核对象处理" objectEntryConditions=""><documentation>{"id":"subProcess1","name":"风控对象组"}</documentation><extensionElements><activiti:formProperty id="CPCP条件" default="" /><activiti:formProperty id="pojoPath" default="BankCModule/processes/reviewCheck/reviewCheck" /></extensionElements></userTask></subProcess><sequenceFlow id="sequenceFlow5" name="" sourceRef="parallelGateway_subProcess1" targetRef="pubObj_subObject1" /><sequenceFlow id="sequenceFlow6" name="" sourceRef="startEvent1" targetRef="subProcess1" /><exclusiveGateway id="exclusiveGateway1" name="网关" /><userTask id="subObject4" name="网关1" objectEntryConditions="" /><sequenceFlow id="sequenceFlow7" name="条件" sourceRef="exclusiveGateway1" targetRef="subObject4"><conditionExpression xsi:type="tFormalExpression">${a=='1'}</conditionExpression></sequenceFlow><userTask id="subObject5" name="网关2" objectEntryConditions="" /><sequenceFlow id="sequenceFlow8" name="条件" sourceRef="exclusiveGateway1" targetRef="subObject5"><conditionExpression xsi:type="tFormalExpression">${a=='2'}</conditionExpression></sequenceFlow><sequenceFlow id="sequenceFlow9" name="" sourceRef="pubObj_subObject1" targetRef="exclusiveGateway1" /><userTask id="subObject6" name="对象" objectEntryConditions="" /><sequenceFlow id="sequenceFlow10" name="" sourceRef="subObject4" targetRef="subObject6" /><sequenceFlow id="sequenceFlow12" name="" sourceRef="subObject6" targetRef="endEvent1" /><sequenceFlow id="sequenceFlow13" name="" sourceRef="subObject5" targetRef="endEvent1" /></process><bpmndi:BPMNDiagram id="BPMNDiagram_通用活动" xmlns="http://www.omg.org/spec/BPMN/20100524/DI"><bpmndi:BPMNPlane bpmnElement="通用活动" id="BPMNPlane_通用活动"><bpmndi:BPMNShape id="BPMNShape_startEvent1" bpmnElement="startEvent1"><omgdc:Bounds x="65" y="85" height="50" width="50" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="BPMNShape_endEvent1" bpmnElement="endEvent1"><omgdc:Bounds x="950" y="185" height="50" width="50" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="BPMNShape_pubObj_subObject1" bpmnElement="pubObj_subObject1"><omgdc:Bounds x="530" y="85" height="50" width="90" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="BPMNShape_authCheck_subObject2" bpmnElement="authCheck_subObject2"><omgdc:Bounds x="40" y="33" height="50" width="90" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="BPMNShape_reviewCheck_subObject3" bpmnElement="reviewCheck_subObject3"><omgdc:Bounds x="160" y="35" height="50" width="90" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="BPMNShape_subProcess1" bpmnElement="subProcess1"><omgdc:Bounds x="230" y="52" height="115" width="265" /></bpmndi:BPMNShape><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow5" bpmnElement="sequenceFlow5"><omgdi:waypoint x="495" y="109.5" /><omgdi:waypoint x="530" y="110" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow6" bpmnElement="sequenceFlow6"><omgdi:waypoint x="115" y="110" /><omgdi:waypoint x="230" y="109.5" /></bpmndi:BPMNEdge><bpmndi:BPMNShape id="BPMNShape_exclusiveGateway1" bpmnElement="exclusiveGateway1"><omgdc:Bounds x="535" y="235" height="30" width="30" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="BPMNShape_subObject4" bpmnElement="subObject4"><omgdc:Bounds x="620" y="145" height="50" width="90" /></bpmndi:BPMNShape><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow7" bpmnElement="sequenceFlow7"><omgdi:waypoint x="565" y="250" /><omgdi:waypoint x="620" y="170" /></bpmndi:BPMNEdge><bpmndi:BPMNShape id="BPMNShape_subObject5" bpmnElement="subObject5"><omgdc:Bounds x="615" y="285" height="50" width="90" /></bpmndi:BPMNShape><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow8" bpmnElement="sequenceFlow8"><omgdi:waypoint x="565" y="250" /><omgdi:waypoint x="615" y="310" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow9" bpmnElement="sequenceFlow9"><omgdi:waypoint x="620" y="110" /><omgdi:waypoint x="535" y="250" /></bpmndi:BPMNEdge><bpmndi:BPMNShape id="BPMNShape_subObject6" bpmnElement="subObject6"><omgdc:Bounds x="810" y="185" height="50" width="90" /></bpmndi:BPMNShape><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow10" bpmnElement="sequenceFlow10"><omgdi:waypoint x="710" y="170" /><omgdi:waypoint x="810" y="210" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow12" bpmnElement="sequenceFlow12"><omgdi:waypoint x="900" y="210" /><omgdi:waypoint x="950" y="210" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="BPMNEdge_sequenceFlow13" bpmnElement="sequenceFlow13"><omgdi:waypoint x="705" y="310" /><omgdi:waypoint x="950" y="210" /></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>
相关文章:

静态解析activiti文本,不入库操作流程
说明: activiti本身状态存库,导致效率太低,把中间状态封装成一个载荷类,返回给上游,下次请求时给带着载荷类即可。 1.pom依赖 <dependency><groupId>net.sf.json-lib</groupId><artifactId>js…...

100个python的基本语法知识【上】
0. 变量和赋值: x 5 name “John” 1. 数据类型: 整数(int) 浮点数(float) 字符串(str) 布尔值(bool) 2. 注释: # 这是单行注释 ""…...

Python从0到100(四十四):读取数据库数据
前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...

ZLMRTCClient配置说明与用法(含示例)
webRTC播放视频 后面在项目中会用到通过推拉播放视频流的技术,所以最近预研了一下webRTC 首先需要引入封装好的webRTC客户端的js文件ZLMRTCClient.js 下面是地址需要的自行下载 http://my.zsyou.top/2024/ZLMRTCClient.js 配置说明 new ZLMRTCClient.Endpoint…...

nginx代理服务配置,基于http协议-Linux(CentOS)
基于http协议的nginx代理服务 1. 打开 Nginx 虚拟机80端口配置文件2. 添加代理配置3. 重启nginx服务 nginx代理缓存配置 1. 打开 Nginx 虚拟机80端口配置文件 Nginx 的默认80端口虚拟机配置文件通常位于/etc/nginx/conf.d/default.conf。 vim /etc/nginx/conf.d/default.con…...

Photos框架 - 自定义媒体资源选择器(数据部分)
引言 在iOS开发中,系统已经为我们提供了多种便捷的媒体资源选择方式,如UIImagePickerController和PHPickerViewController。这些方式不仅使用方便、界面友好,而且我们完全不需要担心性能和稳定性问题,因为它们是由系统提供的&…...

Spring Boot + Spring Cloud 入门
运行配置 java -jar spring-boot-config-0.0.1-SNAPSHOT.jar --spring.profiles.activetest --my1.age32 --debugtrue "D:\Program Files\Redis\redis-server.exe" D:\Program Files\Redis\redis.windows.conf "D:\Program Files\Redis\redis-cli.exe" &q…...

怎么使用动态IP地址上网
如何设置动态IP地址上网? 设置动态IP地址上网的步骤如下: 一、了解动态IP地址 动态IP地址是由网络服务提供商(ISP)动态分配给用户的IP地址,它会根据用户的需求和网络情况实时改变。相比于静态IP地址,动态…...

【源码+文档+调试讲解】智慧物流小程序的设计与实现
摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱,出错率高,信息安全…...

QT:控件圆角设置、固定窗口大小
实现控件圆角度设置//使用的是setStyleSheet方法 //改变的控件是QTextEdit,如果你想改变其他控件,将QTextEdit进行更换 this->setStyleSheet("QTextEdit{background-color:#FFFFFF;border-top-left-radius:15px;border-top-right-radius:15px;bo…...

【JavaScript】深入理解 `let`、`var` 和 `const`
文章目录 一、var 的声明与特点二、let 的声明与特点三、const 的声明与特点四、let、var 和 const 的对比五、实战示例六、最佳实践 在 JavaScript 中,变量声明是编程的基础,而 let、var 和 const 是三种常用的变量声明方式。本文将详细介绍这三种变量声…...

云监控(华为) | 实训学习day7(10)
水一篇。。。。。。。。。。。。。 强迫症打卡必须要满 企拓 今天没有将东西 2024/7/22 规划学习路线对于进入AI行业至关重要。以下是一个详细的学习路线规划,旨在帮助你从零基础到成为一名合格的AI或大数据分析师: 第一阶段:基础知识建设…...

JS_plus.key.addEventListener监听键盘按键
官方文档:https://www.html5plus.org/doc/zh_cn/key.html 监听事件 plus.key.addEventListener(keydown, e > {console.log("keydown: "e.keyCode) }) plus.key.addEventListener(keyup, e > {console.log("keyup: "e.keyCode) })移除事…...

对话系统(Chat)与自主代理(Agent)对撞
随着生成式AI技术的不断进步,关于其未来发展方向的讨论也愈发激烈。究竟生成式AI的未来是在对话系统(Chat)中展现智慧,还是在自主代理(Agent)中体现能力?这一问题引发了广泛的讨论和探索。 首先…...

sql server 连接报错error 40
做个简单的记录,造成40 的原因有很多,你的错误并不一定就是我遇到的这种情况. 错误描述: 首先我在使用ssms 工具连接的时候是可以正常连接的,也能对数据库进行操作. 在使用 ef core 连接 Sql Server 时报错: Microsoft.Data.SqlClient.SqlException (0x80131904): A network-r…...

邮件安全篇:如何防止邮件泄密?
本文主要讨论组织内部用户违反保密规定通过邮件泄密的场景。其他场景导致邮箱泄密的问题(如账号被盗、邮件系统存在安全漏洞等)不在本文的讨论范围。本文主要从邮件系架构设计、邮件数据防泄漏系统、建立健全规章制度、安全意识培训等方面分别探讨。 1. …...

MySQL查询优化:提升数据库性能的策略
在数据库管理和应用中,优化查询是提高MySQL数据库性能的关键环节。随着数据量的不断增长,如何高效地检索和处理数据成为了一个重要的挑战。本文将介绍一系列优化MySQL查询的策略,帮助开发者和管理员提升数据库的性能。 案例1: 使用索引优化查…...

vue-快速入门
Vue 前端体系、前后端分离 1、概述 1.1、简介 Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,可以高效地开发用户界面。…...

【网络流】——初识(最大流)
网络流-最大流 基础信息引入一些概念基本性质 最大流定义 Ford–Fulkerson 增广Edmons−Karp算法Dinic 算法参考文献 基础信息 引入 假定现在有一个无限放水的自来水厂和一个无限收水的小区,他们之间有多条水管和一些节点构成。 每一条水管有三个属性:…...

【STM32嵌入式系统设计与开发---拓展】——1_10矩阵按键
这里写目录标题 1、矩阵按键2、代码片段分析 1、矩阵按键 通过将4x4矩阵按键的每一行依次设为低电平,同时保持其它行为高电平,然后读取所有列的电平状态,可以检测到哪个按键被按下。如果某列变为低电平,说明对应行和列的按键被按下…...

长期更新方法库推荐pmq-ui
# pmq-ui pmq-ui 好用方法库ui库, 欢迎您的使用 ## 安装 1. 克隆项目库到本地: 2. 进入项目目录:cd pmq-ui 3. 安装依赖:npm install pmq-ui ## 使用 <!-- 1. 启动应用: 2. 访问 [http://localhost:3000](http://localhost:300…...

<数据集>抽烟识别数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:4860张 标注数量(xml文件个数):4860 标注数量(txt文件个数):4860 标注类别数:1 标注类别名称:[smoking] 使用标注工具:labelImg 标注规则:对…...

SQL Server 端口设置教程
引言 你好,我是悦创。 在配置 SQL Server 的过程中,设置正确的端口非常关键,因为它影响到客户端如何连接到 SQL Server 实例。默认情况下,SQL Server 使用 TCP 端口 1433,但在多实例服务器上或出于安全考虑ÿ…...

【React1】React概述、基本使用、脚手架、JSX、组件
文章目录 1. React基础1.1 React 概述1.1.1 什么是React1.1.2 React 的特点声明式基于组件学习一次,随处使用1.2 React 的基本使用1.2.1 React的安装1.2.2 React的使用1.2.3 React常用方法说明React.createElement()ReactDOM.render()1.3 React 脚手架的使用1.3.1 React 脚手架…...

k8s部署kafka集群
k8s部署kafka集群 kafka(Kafka with KRaft) mkdir -p ~/kafka-ymlkubectl create ns kafkacat > ~/kafka-yml/kafka.yml << EOF apiVersion: v1 kind: Service metadata:name: kafka-headlessnamespace: kafkalabels:app: kafka spec:type: C…...

(C++回溯01) 组合
77、组合 回溯题目三步走 1. 确定参数 2. 确定终止条件 3. for 循环横向遍历,递归纵向遍历 class Solution { public:vector<vector<int>> result;vector<int> path;void backtracking(int n, int k, int startIndex) {if(path.size() k) {…...

k8s学习笔记——安装istio的仪表盘之prometheus安装
接上一篇,继续安装istio的dashboard。 先到istio-1.22.0/samples/addons目录下,把yaml文件中的镜像仓库地址修改了,修改地址参考我之前写的CSDN里的镜像对照表。不然直接执行kubectl apply -f samples/addons这个命令后,依据会出…...

四、GD32 MCU 常见外设介绍 (7) 7.I2C 模块介绍
7.1.I2C 基础知识 I2C(Inter-Integrated Circuit)总线是一种由Philips公司开发的两线式串行总线,用于内部IC控制的具有多端控制能力的双线双向串行数据总线系统,能够用于替代标准的并行总线,连接各种集成 电路和功能模块。I2C器件能够减少电…...

Apollo 配置中心的部署与使用经验
前言 Apollo(阿波罗)是携程开源的分布式配置管理中心。 本文主要介绍其基于 Docker-Compose 的部署安装和一些使用的经验 特点 成熟,稳定支持管理多环境/多集群/多命名空间的配置配置修改发布实时(1s)通知到应用程序支…...

Perl中的设计模式革新:命令模式的实现与应用
Perl中的设计模式革新:命令模式的实现与应用 在面向对象编程中,设计模式是解决特定问题的成熟模板。命令模式作为行为设计模式之一,它将请求封装为对象,从而允许用户根据不同的请求对客户进行参数化。本文将深入探讨如何在Perl中…...