1、部署流程定义(BPMN文件),获取流程定义文件对象
// resouce:BPMN文件路径,inputStream:该文件的字节流
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().addInputStream(resource, inputStream);
/*根据参数设置流程部署构建器
parameter :部署参数,
一个
Map<String, Object> deploymentBuilder.category(parameter.get("flowType"))
.name(parameter.get("flowName"))
.key(parameter.get("flowKey")).tenantId(parameter.get("flowTenantId"));
*/
// 并获取流程定义部署对象
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、挂起与恢复流程定义,挂起后发起流程实例就会抛出异常
// 挂起
repositoryService.suspendProcessDefinitionById(processDefinitionId);
repositoryService.suspendProcessDefinitionByKey(processDefinitionKey);
// 恢复
repositoryService.activateProcessDefinitionById(processDefinitionId);
repositoryService.activateProcessDefinitionByKey(processDefinitionKey);
3、启动流程实例,并获取流程实例对象
// variables:流程变量,Map<String, Object>类型
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
// 将流程实例与发起人绑定
identityService.setAuthenticatedUserId(userId);
4、对流程实例的操作
processInstance
// 流程实例ID
String processInstanceId = processInstance.getId();
// 判断流程是否结束
processInstance.isEnded();
// 判断流程是否挂起
processInstance.isSuspended();
// 获取流程的发起人ID
String startUserId = processInstance.getStartUserId();
runtimeService
// 该流程的执行对象查询
List<Execution> executionList = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult();
// 该流程实例下的所有活动实例
List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
// 更改多个活动实例的状态节点为指定节点 activityId ,比如结束节点终止流程
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, activityId).changeState();
// 挂起流程实例
runtimeService.suspendProcessInstanceById(processInstanceId);
// 恢复挂起的流程实例
runtimeService.activateProcessInstanceById(processInstanceId);
// 删除一个正在流转的流程 deleteReason:删除原因
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId);
// 获取该流程实例下的任务数量
long count = query.count();
// 任务数量大于1,则流程已经启动了,不能撤回
if (count > 1) {
throw new FlowException(ResultEnum.EX_INSTANCE_BEGIN);
}
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
// 获取流程实例的查询对象
ProcessInstanceQuery instanceQuery = runtimeService.createProcessInstanceQuery();
// 与某个用户相关的
instanceQuery.involvedUser(userId);
// 某个用户开启的
instanceQuery.startedBy(userId);
// 或者查询条件 .or().endOr() ==> (xx or xx or ... ... or xx),等于包裹内容的两括号
instanceQuery.or().endOr();
// 挂起的流程
instanceQuery.suspended();
// 在某个时间点之后开始
instanceQuery.startedAfter(Date date);
// 在某个时间点之前开始
instanceQuery.startedBefore(Date date);
// 获取正在流转的一个指定的流程实例
instanceQuery.processInstanceId(processInstanceId);
// 单个的流程实例
ProcessInstance processInstance = instanceQuery.singleResult();
// 多个流程实例 begin : 从第几个开始 ; max : 展示多少个
List<ProcessInstance> processInstances = instanceQuery.list();
List<ProcessInstance> processInstances = instanceQuery.listPage(int begin,int max);
// 流程实例的数量
long count = taskQuery.count();
historyService
// 获取历史流程实例查询对象
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
// 已完成的
historicProcessInstanceQuery.finished();
// 未完成的
historicProcessInstanceQuery.unfinished();
// 删除的
historicProcessInstanceQuery.deleted();
// 没有删除的
historicProcessInstanceQuery.notDeleted();
// 在某个时间点之后结束
historicProcessInstanceQuery.finishedAfter(Date date);
// 在某个时间点之前结束
historicProcessInstanceQuery.finishedBefore(Date date);
// 指定父流程ID的流程实例 historicProcessInstanceQuery.superProcessInstanceId(processInstanceId)
// 历史流程实例
HistoricProcessInstance processInstance = historicProcessInstanceQuery.processInstanceId(processInstanceId).singleResult();
// 删除该流程的历史记录
historyService.deleteHistoricProcessInstance(processInstanceId);
5、任务服务的操作
获取task任务对象
// 任务基础查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
// 某个任务
taskQuery.taskId(taskId);
// 某个经办人的任务
taskQuery.taskAssignee(userId);
// 某个委托人的任务
taskQuery.taskOwner(userId);
// 某个或多个流程实例的任务
taskQuery.processInstanceId(String processInstanceId);
taskQuery.processInstanceIdIn(List<String> processInstanceIds);
// 某个或多个部署实例的任务
taskQuery.deploymentId(String deploymentId);
taskQuery.deploymentIdIn(List<String> deploymentIds);
// 某个活动实例的任务
taskQuery.executionId(String executionId);
// 按照任务创建时间倒序
taskQuery.orderByTaskCreateTime().desc();
// 存活的任务
taskQuery.active();
// 挂起的任务
taskQuery.suspended();
// 没有 删除原因 的任务
taskQuery.taskWithoutDeleteReason();
// 没有签收的任务
taskQuery.taskUnassigned();
// 单个的任务对象
Task task = taskQuery.singleResult();
// 多个任务对象 begin : 从第几个开始 ; max : 展示多少个
List<Task> tasks = taskQuery.list();
List<Task> tasks = taskQuery.listPage(int begin,int max);
// 任务的数量
long count = taskQuery.count();
变量的设值与取值
// 任务ID
String taskId = task.getId();
// 设置全局变量
taskService.setVariable(taskId,"key1","value1");
// 设置局部变量
taskService.setVariableLocal(taskId,"key2","value2");
// 获取全局变量
Map<String,Object> a = taskService.getVariables(taskId);
// 获取局部变量
Map<String,Object> b = taskService.getVariablesLocal(taskId);
// 流程启动后获取变量(全局变量)
Map<String,Object> variables = runtimeService.getVariables(processInstanceId);
// 设置变量(全局变量)
runtimeService.setVariable(processInstanceId,"key","value");
任务的流转
// 任务的执行(委托人)
taskService.resolveTask(taskId);
taskService.complete(taskId);
// 任务的执行(经办人) variables : 下次任务所需要的参数 localScope : 变量的存储范围(true:作用范围为当前任务,false:表示这个变量是全局的)
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);
// 转发
taskService.setAssignee(taskId, acceptUserId);
// 驳回 currTaskKeys : 该任务的节点 ; activityId : 上一个节点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();
// 删除任务
taskService.deleteTask(taskId, deleteReason);
taskService.deleteTasks(List<String> taskIds, deleteReason);
根据流程实例ID获取流程图(流程图在服务器上的访问地址)
// 1.获取流程实例
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
// 2.根据流程实例ID获取该实例所有的历史轨迹对象
List<HistoricActivityInstance> historyProcess = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId).finished().list();
// 所有的历史轨迹对象
Map<String, HistoricActivityInstance> hisActivityMap = new HashMap<>(16);
historyProcess.forEach(historicActivityInstance -> {
if (!hisActivityMap.containsKey(historicActivityInstance.getActivityId())) { hisActivityMap.put(historicActivityInstance.getActivityId(),historicActivityInstance);
}
});
// 流程定义ID
String processDefinitionId;
// 节点ID的集合
List<String> activityIds = new ArrayList<>();
// 3.获取高亮显示的节点ID和流程定义ID
if (pi == null) {
// 如果流程已经走完了,则从历史记录查询 historyService
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
processDefinitionId = historicProcessInstance.getProcessDefinitionId();
// 获取该流程的结束节点高亮显示
String endActivityId = historicProcessInstance.getEndActivityId();
activityIds.add(endActivityId);
} else {
// 如果流程没有走完,则从运行记录查询 runtimeService
processDefinitionId = pi.getProcessDefinitionId();
activityIds = runtimeService.getActiveActivityIds(instanceId);
}
// 4.获取流程图
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 5.获取流程定义的所有节点信息
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) {
// 获取有效节点的节点信息
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();
// 获取流程图字节流
InputStream in = processDiagramGenerator.generateDiagram(bpmnModel, FlowableConstants.PNG, activityIds, flows, engConf.getActivityFontName(), engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);
// 流程图文件名
String fileName = instanceId.replace("-", "");
// 将流程图保存到本地,并返回流程图在服务器上的访问地址
try {
// ***该方法为本文4.5.6的方法***,应单独封装为一个工具类中的方法
return FileUtil.writeFile(in, filePath, fileName, FlowableConstants.PNG);
} catch (IOException e) {
return null;
}
根据流程定义ID获取流程图(流程图在服务器的访问路径)
// 获取流程图
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的方法***,应单独封装为一个工具类中的方法
return FileUtil.writeFile(inputStream, filePath, fileName, FlowableConstants.PNG);
} catch (IOException e) {
return null;
}
保存文件到服务器,并返回保存文件在服务器的路径
/**
* 保存文件并返回保存文件的路径
*
* @param inputStream 数据流
* @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();
}
}
}