package com.dyttx.util;
import com.sun.istack.internal.NotNull;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.*;
import java.util.zip.ZipInputStream;
/**
* Activiti工具类
*
* @author zh
*/
@Component
public class Activiti7Util {
private static final ProcessEngine PROCESS_ENGINE = ProcessEngines.getDefaultProcessEngine();
/**
* 资源管理类
*/
private static final RepositoryService repositoryService = PROCESS_ENGINE.getRepositoryService();
/**
* 运行时管理类
*/
private static final RuntimeService runtimeService = PROCESS_ENGINE.getRuntimeService();
/**
* 任务管理类
*/
private static final TaskService taskService = PROCESS_ENGINE.getTaskService();
/**
* 历史数据管理类
*/
private static final HistoryService historyService = PROCESS_ENGINE.getHistoryService();
/**
* 流程部署--将bpmn文件放在resources/bpmn 文件夹中进行部署
*
* @param name 部署时候可以起一个名字
* @param bpmnName bpmn文件名[带文件后缀 .bpmn]
* @param bpmnImgName bpmn图片名[带图片后缀]
*/
public static Map<String, Object> importProcessByResources(
@NotNull String name, @NotNull String bpmnName, String bpmnImgName) {
DeploymentBuilder deployment = repositoryService.createDeployment();
deployment.name(name);
deployment.addClasspathResource("bpmn/" + bpmnName);
if (bpmnImgName != null) {
deployment.addClasspathResource("bpmn/" + bpmnImgName);
}
// 执行部署
Deployment deploy = deployment.deploy();
return getMap(deploy);
}
/**
* 流程部署-- 通过zip包进行bpmn文件部署
*
* @param zipPath: zip文件的路径 带[.zip] 后缀
* @param name: 给部署起一个名字
*/
public static Map<String, Object> importProcessByZip(String zipPath, String name)
throws FileNotFoundException {
FileInputStream fileInputStream = new FileInputStream(zipPath);
ZipInputStream stream = new ZipInputStream(fileInputStream);
Deployment deploy =
repositoryService
.createDeployment()
.addZipInputStream(stream)
.name(name)
.deploy();
return getMap(deploy);
}
private static Map<String, Object> getMap(Deployment deploy) {
Map<String, Object> map = new HashMap<>(4);
// 部署id
map.put("deploymentId", deploy.getId());
// 部署名称
map.put("deploymentName", deploy.getName());
// 部署时间
map.put("deploymentTime", deploy.getDeploymentTime());
return map;
}
/**
* 查询流程定义集合【流程定义模板列表】
*
* @param key bpmn文件中的 processId processId = null 则查全部模板
*/
public static List<Map<String, Object>> queryProcessDefinition(String key) {
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
if (key != null) {
// 根据指定key查出模板
query.processDefinitionKey(key);
}
List<Map<String, Object>> result = new ArrayList<>();
List<ProcessDefinition> list = query.list();
for (ProcessDefinition processDefinition : list) {
Map<String, Object> map = new HashMap<>(8);
// 流程部署id
map.put("deploymentId", processDefinition.getDeploymentId());
// 流程定义id
map.put("processDefinitionId", processDefinition.getId());
// 流程定义key
map.put("processDefinitionKey", processDefinition.getKey());
// 流程定义名称
map.put("processDefinitionName", processDefinition.getName());
// 流程定义版本
map.put("processDefinitionVersion", processDefinition.getVersion());
result.add(map);
}
return result;
}
/**
* 删除流程部署信息
*
* @param deploymentId 流程部署id
* @param cascade: true-连同已经存在的运行任务一起删除 false-不删除运行的任务
* @author zh
*/
public static void deleteProcessDefinition(String deploymentId, boolean cascade) {
repositoryService.deleteDeployment(deploymentId, cascade);
}
/**
* 根据指定的bpmn的 processId 下载已经存在数据库中的文件 需要 common-io.jar
*
* @param key bpmn文件中的 processId
* @param imgSavePath 需要把对应的图片文件保存的绝对路径【例:D:/bpmn/test-image.png】
* @param bpmnSavePath 需要把对应的bpmn文件保存的绝对路径【例:D:/bpmn/test-bpmn.bpmn】
*/
public static void downDeployment(String key, String imgSavePath, String bpmnSavePath) {
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
// 根据指定key查出模板
query.processDefinitionKey(key);
for (ProcessDefinition processDefinition : query.list()) {
// 拿到deploymentId
String deploymentId = processDefinition.getDeploymentId();
// 图片目录和名称
String pngName = processDefinition.getDiagramResourceName();
InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, pngName);
String bpmnName = processDefinition.getResourceName();
InputStream bpmnNameResourceAsStream =
repositoryService.getResourceAsStream(deploymentId, bpmnName);
File pngFile = new File(imgSavePath);
File bpmnFile = new File(bpmnSavePath);
FileOutputStream pngFileOutputStream = null;
FileOutputStream bpmnFileOutputStream = null;
try {
pngFileOutputStream = new FileOutputStream(pngFile);
bpmnFileOutputStream = new FileOutputStream(bpmnFile);
IOUtils.copy(resourceAsStream, pngFileOutputStream);
IOUtils.copy(bpmnNameResourceAsStream, bpmnFileOutputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流输入流
try {
resourceAsStream.close();
bpmnNameResourceAsStream.close();
assert pngFileOutputStream != null;
assert bpmnFileOutputStream != null;
// 关闭流输出流
pngFileOutputStream.close();
bpmnFileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 开启一个流程实例
*
* @param processDefinitionId 流程定义id
* @param businessKey 可以绑定一个自定义的业务id
* @param params: key:在bpmn文件中定义的变量占位符【例: ${userName}】 value:对应的占位值 【例: 小明】
* @author zh
*/
public static Map<String, Object> startProcessInstanceByKey(
String processDefinitionId, String businessKey, Map<String, Object> params) {
// 根据流程定义ID启动流程
ProcessInstance one;
if(StringUtils.isBlank(businessKey)){
one = runtimeService.startProcessInstanceByKey(processDefinitionId, params);
}else {
one = runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, params);
}
Map<String, Object> map = new HashMap<>(4);
// 流程定义id
map.put("processDefinitionId", one.getProcessDefinitionId());
// 流程实例id
map.put("id", one.getId());
// 当前活动id
map.put("activityId", one.getActivityId());
return map;
}
/**
* 开启一个流程实例
*
* @param processDefinitionId 流程定义id
* @param businessKey 可以绑定一个自定义的业务id
* @author zh
*/
public static Map<String, Object> startProcessInstanceByKey(
String processDefinitionId, String businessKey) {
// 根据流程定义ID启动流程
ProcessInstance one;
if(StringUtils.isBlank(businessKey)){
one = runtimeService.startProcessInstanceByKey(processDefinitionId);
}else {
one = runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey);
}
Map<String, Object> map = new HashMap<>(4);
// 流程定义id
map.put("processDefinitionId", one.getProcessDefinitionId());
// 流程实例id
map.put("id", one.getId());
// 当前活动id
map.put("activityId", one.getActivityId());
return map;
}
/**
* 【如果某个任务设置了负责人】则可通过该方法查询负责人【根据人名查出 自己有哪些任务待完成】
*
* @param key bpmn里面的id值
* @param assignee:负责人名
* @author zh
*/
public static List<Map<String, Object>> taskListByAssignee(String key, String assignee) {
// 获取已经运行的任务列表
List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee).list();
return getMaps(taskList);
}
/**
* 【如果某个任务设置了候选人】则可通过该方法查询候选人【根据人名查出 自己有哪些任务待完成】
*
* @param key bpmn里面的id值
* @param candidateUserName: 候选人名
* @author zh
*/
public static List<Map<String, Object>> taskListByCandidateUser(String key, String candidateUserName) {
// 获取 已经运行的任务列表
List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(key).taskCandidateUser(candidateUserName).list();
return getMaps(taskList);
}
private static List<Map<String, Object>> getMaps(List<Task> taskList) {
List<Map<String, Object>> result = new ArrayList<>();
for (Task task : taskList) {
Map<String, Object> map = new HashMap<>(8);
// 流程实例id
map.put("processInstanceId", task.getProcessInstanceId());
// 任务id
map.put("id", task.getId());
// 任务负责人
map.put("assignee", task.getAssignee());
// 任务名称
map.put("name", task.getName());
// 任务创建时间
map.put("createTime", task.getCreateTime());
result.add(map);
}
return result;
}
/**
* 添加候选人
*
*@param taskId 任务id
*@param userId 候选人
*@author zh
*/
public static void addGroupUser(String taskId, String userId){
taskService.addCandidateUser(taskId, userId);
}
/**
* 删除候选人
*
*@param taskId 任务id
*@param userId 候选人
*@author zh
*/
public static void deleteGroupUser(String taskId, String userId){
taskService.deleteCandidateUser(taskId, userId);
}
/**
* 【如果某个任务设置了候选人】 某个负责人进行拾取任务【通过任务id和人名 开始拾取任务】
*
* @param taskId: 任务id
* @param candidateUserName 候选人名
* @return true-拾取成功 false=拾取失败
* @author zh
*/
public static boolean claimTask(String taskId, String candidateUserName) {
// 根据条件 查出任务
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
// 能查到任务并且 传入参数也符合候选人 才能进行拾取
if (task != null && isCandidate(taskId, candidateUserName)) {
// 进行拾取操作 其实就是把指定任务的assignee设置对应的负责人名
taskService.claim(task.getId(), candidateUserName);
return true;
}
return false;
}
/**
* 判断指定任务的候选人名单中是否有: candidateUserName
*
* @return true:是候选人 false:不是候选人
*/
private static boolean isCandidate(String taskId, String candidateUserName) {
for (IdentityLink link : taskService.getIdentityLinksForTask(taskId)) {
if (candidateUserName.equals(link.getUserId())) {
return true;
}
}
return false;
}
/**
* [描述]【如果某个任务设置了候选人】 负责人已经拾取某个任务以后 打算再归还回去
*
* @param taskId: 任务id
* @param candidateUserName 候选人名
* @author zh
*/
public static boolean claimTaskReturn(String taskId, String candidateUserName) {
// 根据条件 查出任务
Task task =
taskService
.createTaskQuery()
.taskId(taskId)
.taskCandidateUser(candidateUserName)
.singleResult();
if (task != null) {
// 归还操作 其实就是把该任务的 assignee 设置成null
taskService.setAssignee(task.getId(), null);
return true;
}
return false;
}
/**
* 【如果某个任务设置了候选人】某个任务虽然是自己的 但是可以交给其他人进行完成
*
* @param taskId: 任务id
* @param candidateUserName 候选人名
* @param assigneeName: 交接人
* @author zh
*/
public static boolean taskHandover(String taskId, String candidateUserName, String assigneeName) {
// 根据条件 查出任务
Task task =
taskService
.createTaskQuery()
.taskId(taskId)
.taskCandidateUser(candidateUserName)
.singleResult();
// 交接操作 这个任务是自己虽然是候选人 但是 可以直接把这个任务交接给别人进行完成
if (task != null) {
taskService.setAssignee(task.getId(), assigneeName);
return true;
}
return false;
}
/**
* 根据名字 查询个人待执行的任务【已经把任务拾取了】【带分页】
*
* @param taskAssignName 人名【例:班长、经理、总经理等...】
* @param key bpmn文件中的processId
* @param firstResult 当前页【默认从0开始】
* @param maxResults 页长
*/
public static List<Map<String, Object>> taskListByMy(
String taskAssignName, String key, Integer firstResult, Integer maxResults) {
List<Task> list =
taskService
.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(taskAssignName)
.listPage(firstResult, maxResults);
List<Map<String, Object>> result = new ArrayList<>();
for (Task task : list) {
Map<String, Object> taskMap = new HashMap<>(8);
// 任务id
taskMap.put("taskId", task.getId());
// 任务名称
taskMap.put("taskName", task.getName());
// 创建时间
taskMap.put("createTime", task.getCreateTime());
// 任务负责人
taskMap.put("taskAssignee", task.getAssignee());
// 流程实例id
taskMap.put("processInstanceId", task.getProcessInstanceId());
result.add(taskMap);
}
return result;
}
/**
* 完成个人任务
*
* @param taskAssignName: 任务代理人
* @param taskId: 任务id params: 流程连接线上的变量 【例】假如流程线上面有一个变量名 ${audit=='通过'}
* 则调用时候:params.put("audit","通过"); 这里执行时,会判断控制线的变量 从而控制流程走向
*/
public static boolean completeTask(String taskAssignName, String taskId, Map<String, Object> params) {
try {
Task task = taskService.createTaskQuery().taskId(taskId).taskAssignee(taskAssignName).singleResult();
if (task == null) {
// 说明根据任务id和人名 无法查到待办的指定任务
return false;
}
taskService.complete(taskId, params);
return true;
} catch (ActivitiException ee) {
ee.printStackTrace();
//流程线上已经绑定变量了
return false;
} catch (Exception e) {
e.printStackTrace();
System.out.println("【error】 执行报错: " + e.getMessage());
return false;
}
}
/**
* 完成个人任务
*
* @param taskAssignName: 任务代理人
* @param taskId: 任务id params: 流程连接线上的变量 【例】假如流程线上面有一个变量名 ${audit=='通过'}
* 则调用时候:params.put("audit","通过"); 这里执行时,会判断控制线的变量 从而控制流程走向
*/
public static boolean completeTask(String taskAssignName, String taskId) {
try {
Task task = taskService.createTaskQuery().taskId(taskId).taskAssignee(taskAssignName).singleResult();
if (task == null) {
// 说明根据任务id和人名 无法查到待办的指定任务
return false;
}
taskService.complete(taskId);
return true;
} catch (ActivitiException ee) {
ee.printStackTrace();
//流程线上已经绑定变量了
return false;
} catch (Exception e) {
e.printStackTrace();
System.out.println("【error】 执行报错: " + e.getMessage());
return false;
}
}
/**
* 先执行拾取任务,再进行完成任务。
*
* @author zh
*/
public static boolean claimTaskAndCompleteTask(
String taskId, String candidateUserName, Map<String, Object> params) {
if (claimTask(taskId, candidateUserName)) {
completeTask(candidateUserName, taskId, params);
return true;
}
return false;
}
/**
* 先执行拾取任务,再进行完成任务。
*
* @author zh
*/
public static boolean claimTaskAndCompleteTask(
String taskId, String candidateUserName) {
if (claimTask(taskId, candidateUserName)) {
completeTask(candidateUserName, taskId);
return true;
}
return false;
}
/**
* 根据相应的条件 查出历史的任务信息
*
* @param processDefinitionId: 流程定义id
* @param processInstanceId: 流程实例id
* @param assigneeName: 代理人名
* @author zh
*/
public static List<HistoricActivityInstance> historicActivityInstanceList(
String processDefinitionId, String processInstanceId, String assigneeName) {
// 例子:查询 act_hi_actinst 表中数据
HistoricActivityInstanceQuery instanceQuery =
historyService.createHistoricActivityInstanceQuery();
if (processDefinitionId != null) {
// 查询条件: 根据流程定义id 拿到数据
instanceQuery.processDefinitionId(processDefinitionId);
}
if (processInstanceId != null) {
// 查询条件: 根据流程实例id 拿到数据
instanceQuery.processInstanceId(processInstanceId);
}
if (assigneeName != null) {
instanceQuery.taskAssignee(assigneeName);
}
return instanceQuery.list();
}
/**
* 通过流程定义id --》 [挂起【暂停】] 或 [激活【启动】] 全部流程实例的执行
*
* @author zh
*/
public static void suspendAllProcessInstance(String key) {
// 通过指定的key 获取单个流程定义
ProcessDefinition processDefinition =
repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).singleResult();
// 判断指定的流程定义 是否挂起 true=挂起 false=激活
boolean suspended = processDefinition.isSuspended();
// 拿到流程定义id
String processDefinitionId = processDefinition.getId();
if (suspended) {
// 说明原来是挂起的 则可以对流程定义和旗下的所有流程实例进行激活操作
// 参数说明:processDefinitionId=流程定义id 、 activateProcessInstances=挂起或者激活、activationDate=执行事件
repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
System.out.println("对流程定义id为" + processDefinitionId + ",进行[激活]操作");
} else {
// 说明原来是激活的 则可以对流程定义和旗下的所有流程实例进行挂起操作
repositoryService.activateProcessDefinitionById(processDefinitionId, false, null);
System.out.println("对流程定义id为" + processDefinitionId + ",进行[挂起]操作");
}
System.out.println("流程定义" + processDefinition.getName() + "已经操作成功【包括关联的所有实例】");
}
/**
* 针对某一个流程实例进行【挂起】或【激活】操作
*
* @author zh
*/
public static void suspendProcessInstanceByProcessInstanceId(String processInstanceId) {
ProcessInstance instance =
runtimeService
.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
// 原来是挂起的
if (instance.isSuspended()) {
runtimeService.activateProcessInstanceById(instance.getId());
System.out.println("流程实例id=" + instance.getId() + ",已激活");
} else {
runtimeService.suspendProcessInstanceById(instance.getId());
System.out.println("流程实例id=" + instance.getId() + ",已挂起");
}
System.out.println("单个流程实例:" + instance.getName() + ",已经操作成功");
}
}
Activiti7工具类,常用方法封装
最新推荐文章于 2022-10-10 20:02:27 发布