1、部署流程定義(BPMN文件)柏蘑,獲取流程定義文件對(duì)象
// resouce:BPMN文件路徑幸冻,inputStream:該文件的字節(jié)流
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().addInputStream(resource, inputStream);
/*根據(jù)參數(shù)設(shè)置流程部署構(gòu)建器
parameter :部署參數(shù),
一個(gè)
Map<String, Object> deploymentBuilder.category(parameter.get("flowType"))
.name(parameter.get("flowName"))
.key(parameter.get("flowKey")).tenantId(parameter.get("flowTenantId"));
*/
// 并獲取流程定義部署對(duì)象
Deployment deployment = deploymentBuilder.deploy();
String deploymentId = deployment.getId();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
// 流程定義ID
String processDefinitionId = processDefinition.getId();
// 流程定義Key
String processDefinitionKey = processDefinition.getKey();
2咳焚、掛起與恢復(fù)流程定義洽损,掛起后發(fā)起流程實(shí)例就會(huì)拋出異常
// 掛起
repositoryService.suspendProcessDefinitionById(processDefinitionId);
repositoryService.suspendProcessDefinitionByKey(processDefinitionKey);
// 恢復(fù)
repositoryService.activateProcessDefinitionById(processDefinitionId);
repositoryService.activateProcessDefinitionByKey(processDefinitionKey);
3、啟動(dòng)流程實(shí)例革半,并獲取流程實(shí)例對(duì)象
// variables:流程變量碑定,Map<String, Object>類型
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
// 將流程實(shí)例與發(fā)起人綁定
identityService.setAuthenticatedUserId(userId);
4、對(duì)流程實(shí)例的操作
processInstance
// 流程實(shí)例ID
String processInstanceId = processInstance.getId();
// 判斷流程是否結(jié)束
processInstance.isEnded();
// 判斷流程是否掛起
processInstance.isSuspended();
// 獲取流程的發(fā)起人ID
String startUserId = processInstance.getStartUserId();
runtimeService
// 該流程的執(zhí)行對(duì)象查詢
List<Execution> executionList = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult();
// 該流程實(shí)例下的所有活動(dòng)實(shí)例
List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
// 更改多個(gè)活動(dòng)實(shí)例的狀態(tài)節(jié)點(diǎn)為指定節(jié)點(diǎn) activityId 又官,比如結(jié)束節(jié)點(diǎn)終止流程
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, activityId).changeState();
// 掛起流程實(shí)例
runtimeService.suspendProcessInstanceById(processInstanceId);
// 恢復(fù)掛起的流程實(shí)例
runtimeService.activateProcessInstanceById(processInstanceId);
// 刪除一個(gè)正在流轉(zhuǎn)的流程 deleteReason:刪除原因
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId);
// 獲取該流程實(shí)例下的任務(wù)數(shù)量
long count = query.count();
// 任務(wù)數(shù)量大于1延刘,則流程已經(jīng)啟動(dòng)了,不能撤回
if (count > 1) {
throw new FlowException(ResultEnum.EX_INSTANCE_BEGIN);
}
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
// 獲取流程實(shí)例的查詢對(duì)象
ProcessInstanceQuery instanceQuery = runtimeService.createProcessInstanceQuery();
// 與某個(gè)用戶相關(guān)的
instanceQuery.involvedUser(userId);
// 某個(gè)用戶開啟的
instanceQuery.startedBy(userId);
// 或者查詢條件 .or().endOr() ==> (xx or xx or ... ... or xx)六敬,等于包裹內(nèi)容的兩括號(hào)
instanceQuery.or().endOr();
// 掛起的流程
instanceQuery.suspended();
// 在某個(gè)時(shí)間點(diǎn)之后開始
instanceQuery.startedAfter(Date date);
// 在某個(gè)時(shí)間點(diǎn)之前開始
instanceQuery.startedBefore(Date date);
// 獲取正在流轉(zhuǎn)的一個(gè)指定的流程實(shí)例
instanceQuery.processInstanceId(processInstanceId);
// 單個(gè)的流程實(shí)例
ProcessInstance processInstance = instanceQuery.singleResult();
// 多個(gè)流程實(shí)例 begin : 從第幾個(gè)開始 碘赖; max : 展示多少個(gè)
List<ProcessInstance> processInstances = instanceQuery.list();
List<ProcessInstance> processInstances = instanceQuery.listPage(int begin,int max);
// 流程實(shí)例的數(shù)量
long count = taskQuery.count();
historyService
// 獲取歷史流程實(shí)例查詢對(duì)象
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
// 已完成的
historicProcessInstanceQuery.finished();
// 未完成的
historicProcessInstanceQuery.unfinished();
// 刪除的
historicProcessInstanceQuery.deleted();
// 沒有刪除的
historicProcessInstanceQuery.notDeleted();
// 在某個(gè)時(shí)間點(diǎn)之后結(jié)束
historicProcessInstanceQuery.finishedAfter(Date date);
// 在某個(gè)時(shí)間點(diǎn)之前結(jié)束
historicProcessInstanceQuery.finishedBefore(Date date);
// 指定父流程ID的流程實(shí)例 historicProcessInstanceQuery.superProcessInstanceId(processInstanceId)
// 歷史流程實(shí)例
HistoricProcessInstance processInstance = historicProcessInstanceQuery.processInstanceId(processInstanceId).singleResult();
// 刪除該流程的歷史記錄
historyService.deleteHistoricProcessInstance(processInstanceId);
5、任務(wù)服務(wù)的操作
獲取task任務(wù)對(duì)象
// 任務(wù)基礎(chǔ)查詢對(duì)象
TaskQuery taskQuery = taskService.createTaskQuery();
// 某個(gè)任務(wù)
taskQuery.taskId(taskId);
// 某個(gè)經(jīng)辦人的任務(wù)
taskQuery.taskAssignee(userId);
// 某個(gè)委托人的任務(wù)
taskQuery.taskOwner(userId);
// 某個(gè)或多個(gè)流程實(shí)例的任務(wù)
taskQuery.processInstanceId(String processInstanceId);
taskQuery.processInstanceIdIn(List<String> processInstanceIds);
// 某個(gè)或多個(gè)部署實(shí)例的任務(wù)
taskQuery.deploymentId(String deploymentId);
taskQuery.deploymentIdIn(List<String> deploymentIds);
// 某個(gè)活動(dòng)實(shí)例的任務(wù)
taskQuery.executionId(String executionId);
// 按照任務(wù)創(chuàng)建時(shí)間倒序
taskQuery.orderByTaskCreateTime().desc();
// 存活的任務(wù)
taskQuery.active();
// 掛起的任務(wù)
taskQuery.suspended();
// 沒有 刪除原因 的任務(wù)
taskQuery.taskWithoutDeleteReason();
// 沒有簽收的任務(wù)
taskQuery.taskUnassigned();
// 單個(gè)的任務(wù)對(duì)象
Task task = taskQuery.singleResult();
// 多個(gè)任務(wù)對(duì)象 begin : 從第幾個(gè)開始 外构; max : 展示多少個(gè)
List<Task> tasks = taskQuery.list();
List<Task> tasks = taskQuery.listPage(int begin,int max);
// 任務(wù)的數(shù)量
long count = taskQuery.count();
變量的設(shè)值與取值
// 任務(wù)ID
String taskId = task.getId();
// 設(shè)置全局變量
taskService.setVariable(taskId,"key1","value1");
// 設(shè)置局部變量
taskService.setVariableLocal(taskId,"key2","value2");
// 獲取全局變量
Map<String,Object> a = taskService.getVariables(taskId);
// 獲取局部變量
Map<String,Object> b = taskService.getVariablesLocal(taskId);
// 流程啟動(dòng)后獲取變量(全局變量)
Map<String,Object> variables = runtimeService.getVariables(processInstanceId);
// 設(shè)置變量(全局變量)
runtimeService.setVariable(processInstanceId,"key","value");
任務(wù)的流轉(zhuǎn)
// 任務(wù)的執(zhí)行(委托人)
taskService.resolveTask(taskId);
taskService.complete(taskId);
// 任務(wù)的執(zhí)行(經(jīng)辦人) variables : 下次任務(wù)所需要的參數(shù) localScope : 變量的存儲(chǔ)范圍(true:作用范圍為當(dāng)前任務(wù),false:表示這個(gè)變量是全局的)
taskService.complete(taskId);
taskService.complete(String taskId, Map<String, Object> variables);
taskService.complete(String taskId, Map<String, Object> variables, boolean localScope);
// 添加和刪除候選人
taskService.addCandidateUser(taskId, userId);
taskService.deleteCandidateUser(taskId, userId);
// 簽收
taskService.claim(taskId, userId);
// 委派
taskService.delegateTask(taskId, acceptUserId);
// 轉(zhuǎn)發(fā)
taskService.setAssignee(taskId, acceptUserId);
// 駁回 currTaskKeys : 該任務(wù)的節(jié)點(diǎn) 普泡; activityId : 上一個(gè)節(jié)點(diǎn)ID
List<String> currTaskKeys = new ArrayList<>();
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
for (Task task : tasks) {
currTaskKeys.add(task.getTaskDefinitionKey());
}
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(processInstanceId)
.moveActivityIdsToSingleActivityId(currTaskKeys, activityId)
.changeState();
// 刪除任務(wù)
taskService.deleteTask(taskId, deleteReason);
taskService.deleteTasks(List<String> taskIds, deleteReason);
根據(jù)流程實(shí)例ID獲取流程圖(流程圖在服務(wù)器上的訪問地址)
// 1.獲取流程實(shí)例
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
// 2.根據(jù)流程實(shí)例ID獲取該實(shí)例所有的歷史軌跡對(duì)象
List<HistoricActivityInstance> historyProcess = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId).finished().list();
// 所有的歷史軌跡對(duì)象
Map<String, HistoricActivityInstance> hisActivityMap = new HashMap<>(16);
historyProcess.forEach(historicActivityInstance -> {
if (!hisActivityMap.containsKey(historicActivityInstance.getActivityId())) { hisActivityMap.put(historicActivityInstance.getActivityId(),historicActivityInstance);
}
});
// 流程定義ID
String processDefinitionId;
// 節(jié)點(diǎn)ID的集合
List<String> activityIds = new ArrayList<>();
// 3.獲取高亮顯示的節(jié)點(diǎn)ID和流程定義ID
if (pi == null) {
// 如果流程已經(jīng)走完了,則從歷史記錄查詢 historyService
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
processDefinitionId = historicProcessInstance.getProcessDefinitionId();
// 獲取該流程的結(jié)束節(jié)點(diǎn)高亮顯示
String endActivityId = historicProcessInstance.getEndActivityId();
activityIds.add(endActivityId);
} else {
// 如果流程沒有走完审编,則從運(yùn)行記錄查詢 runtimeService
processDefinitionId = pi.getProcessDefinitionId();
activityIds = runtimeService.getActiveActivityIds(instanceId);
}
// 4.獲取流程圖
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 5.獲取流程定義的所有節(jié)點(diǎn)信息
Map<String, FlowElement> activityMap = new HashMap<>(16);
List<Process> processes = bpmnModel.getProcesses();
for (Process process : processes) {
Collection<FlowElement> flowElements = process.getFlowElements();
for (FlowElement flowElement : flowElements) {
if (flowElement != null) {
String flowElementId = flowElement.getId();
activityMap.put(flowElementId, flowElement);
}
}
}
// 6.獲取高亮顯示的連線集合
List<String> flows = new ArrayList<>();
// 遞歸獲取高亮連線
for (String activityId : activityIds) {
this.getHighLightedFlows(activityMap, hisActivityMap, activityId, flows,activityId);
// 遞歸方法
private void getHighLightedFlows(Map<String, FlowElement> flowNodeMap,Map<String, HistoricActivityInstance> hisActivityMap,String activeActivityId,List<String> highLightedFlows,String oldActivityId) {
// 獲取有效節(jié)點(diǎn)的節(jié)點(diǎn)信息
FlowElement flowElement = flowNodeMap.get(activeActivityId);
FlowNode flowNode = (FlowNode) flowElement;
// 獲取連線信息集合
List<SequenceFlow> incomingFlows = flowNode.getIncomingFlows();
for (SequenceFlow sequenceFlow : incomingFlows) {
// 獲取連線ID
String sourceRefId = sequenceFlow.getSourceRef();
if (hisActivityMap.containsKey(sourceRefId) && !oldActivityId.equals(sourceRefId)) {
highLightedFlows.add(sequenceFlow.getId());
this.getHighLightedFlows(flowNodeMap, hisActivityMap, sourceRefId, highLightedFlows, oldActivityId);
} else {
if (hisActivityMap.containsKey(sourceRefId)) {
highLightedFlows.add(sequenceFlow.getId());
}
break;
}
}
}
}
// 獲取流程引擎配置
ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();
// 定義流程畫布生成器
ProcessDiagramGenerator processDiagramGenerator = engConf.getProcessDiagramGenerator();
// 獲取流程圖字節(jié)流
InputStream in = processDiagramGenerator.generateDiagram(bpmnModel, FlowableConstants.PNG, activityIds, flows, engConf.getActivityFontName(), engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);
// 流程圖文件名
String fileName = instanceId.replace("-", "");
// 將流程圖保存到本地撼班,并返回流程圖在服務(wù)器上的訪問地址
try {
// ***該方法為本文4.5.6的方法***,應(yīng)單獨(dú)封裝為一個(gè)工具類中的方法
return FileUtil.writeFile(in, filePath, fileName, FlowableConstants.PNG);
} catch (IOException e) {
return null;
}
根據(jù)流程定義ID獲取流程圖(流程圖在服務(wù)器的訪問路徑)
// 獲取流程圖
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 獲取流程引擎配置
ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();
// 定義流程畫布生成器
ProcessDiagramGenerator processDiagramGenerator = engConf.getProcessDiagramGenerator();
InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel,FlowableConstants.PNG,engConf.getActivityFontName(),engConf.getLabelFontName(),engConf.getAnnotationFontName(),engConf.getClassLoader(),1.0,true);
// 流程圖文件名
String fileName = bpmnModel.getTargetNamespace();
if (fileName == null || "".equals(fileName)) {
fileName = processDefinitionId.substring(0, processDefinitionId.indexOf(":")).replace("-", "");
}
// 將流程圖保存到本地
try {
// ***該方法為本文4.5.6的方法***垒酬,應(yīng)單獨(dú)封裝為一個(gè)工具類中的方法
return FileUtil.writeFile(inputStream, filePath, fileName, FlowableConstants.PNG);
} catch (IOException e) {
return null;
}
保存文件到服務(wù)器砰嘁,并返回保存文件在服務(wù)器的路徑
/**
* 保存文件并返回保存文件的路徑
*
* @param inputStream 數(shù)據(jù)流
* @param path 保存路徑
* @param fileName 文件名
* @param fileType 文件類型
* @return
*/
public static String writeFile(InputStream inputStream, String path, String fileName, String fileType) throws IOException {
OutputStream out = null;
// 按照文件類型分目錄存放
String folderPath = path + "/" + fileType + "/";
File file = new File(folderPath);
// 判斷目錄是否存在
if (!file.exists()) {
file.mkdirs();
}
// 完整文件名
String fileNames = fileName + "." + fileType;
// 文件存放路徑
String filePath = folderPath + fileNames;
File image = new File(filePath);
image.createNewFile();
byte[] bytes = new byte[1024];
int length = 0;
try {
out = new FileOutputStream(image);
while ((length = inputStream.read(bytes)) != -1) {
out.write(bytes, 0, length);
}
return fileType + "/" + fileNames;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (out != null) {
out.close();
}
}
}