目录
5、使用会签的节点(会签:当前节点所有用户都执行完任务才会流转到下一个节点)
6、给箭头添加监听(此处用在指向会签的箭头,为会签节点manageList添加用户)
9、执行流程相关操作(都为ActivitiUtil中的方法)
12、对应的activiti工具类(ActivitiUtil类和JDJumpTaskCmd类)
1、IDEA安装activiti编辑插件
2、将新增的bmpn文件放到resource下
3、画bmpn流程图
4、给节点添加监听(监听可以给每个节点分配用户)
监听例子:
public class TaskListListener implements TaskListener {
private ActivitiMapper activitiMapper = SpringContextHolder.getBean(ActivitiMapper.class);
@Override
public void notify(DelegateTask delegateTask) {
String taskName = delegateTask.getName();
List<String> listId = new ArrayList<>();
switch (taskName) {
case "环委办(督查科)发布任务":
List<String> inspectorId = activitiMapper.findInspectorId();
delegateTask.addCandidateUsers(inspectorId);
break;
case"牵头单位分发任务":
String leadCooperate = activitiMapper.findLeadCooperate(delegateTask.getProcessDefinitionId());
listId.add(leadCooperate);
delegateTask.addCandidateUsers(listId);
break;
case"牵头单位完成任务":
String leadCooperate1 = activitiMapper.findLeadCooperate(delegateTask.getProcessDefinitionId());
listId.add(leadCooperate1);
delegateTask.addCandidateUsers(listId);
break;
case"责任科室审核材料":
String office = activitiMapper.findOffice(delegateTask.getProcessDefinitionId());
listId.add(office);
delegateTask.addCandidateUsers(listId);
break;
case"环委办(督查科)接收材料":
List<String> inspectorId1 = activitiMapper.findInspectorId();
delegateTask.addCandidateUsers(inspectorId1);
break;
default:
break;
}
}
}
5、使用会签的节点(会签:当前节点所有用户都执行完任务才会流转到下一个节点)
会签设置:${nrOfCompletedInstances/nrOfInstances==1}
${manageList}为会签节点所有用户集合 manage为集合元素
6、给箭头添加监听(此处用在指向会签的箭头,为会签节点manageList添加用户)
public class TaskListLineListener implements ExecutionListener {
private ActivitiMapper activitiMapper = SpringContextHolder.getBean(ActivitiMapper.class);
@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
Map<String, Object> map= new HashMap<>();
List<String> manageList = new ArrayList<>();
List<String> cooperates = new ArrayList<>();
List<String> units = new ArrayList<>();
String cooperate = activitiMapper.findCooperate(delegateExecution.getProcessDefinitionId());
String unit = activitiMapper.findUnit(delegateExecution.getProcessDefinitionId());
if(!ObjectUtils.isEmpty(cooperate)){
cooperates = Arrays.asList(cooperate.split(","));
}
if(!ObjectUtils.isEmpty(unit)){
units = Arrays.asList(unit.split(","));
}
manageList.addAll(units);
manageList.addAll(cooperates);
map.put("manageList", manageList);
delegateExecution.setVariables(map);
}
}
7、给箭头添加执行条件
8、普通节点执行和有条件的节点执行操作
(1)结合当前条件查询初对应表ACT_RU_TASK中的任务id---- taskId
(2)执行ActivitiUtil的next方法: next(taskId, null);
(3)针对有条件的节点:
Map<String, Object> varabies = new HashMap<>();
varabies.put("message", "yes");
next(taskId, varabies);
9、执行流程相关操作(都为ActivitiUtil中的方法)
//发布任务(参数为模板名称和classPath)
Deployment deployment = releaseProcess("任务流程图", "processes/taskList.bpmn");
//启动任务流程
startProcess("taskList", "", null, null); taskList为模板id
//执行任务
next(taskId, null);
//退回到上一节点
regression(taskId);
//删除任务
deleteProcess(String deploymentId, boolean isDelete)
true:级联删除 删除当前规则下的所以信息,包括正在执行的和历史的信息
10、涉及的表单
11、网关
(1)排他网关(选择满足条件的流程流转)
(2)并行网关(所有流程需全部执行完成才会继续流转)
12、对应的activiti工具类(ActivitiUtil类和JDJumpTaskCmd类)
public class ActivitiUtil {
//Activiti中最核心的类,其他的类都是由他而来
private static ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//执行管理,包括启动、推进、删除流程实例等操作
private static RuntimeService runtimeService = processEngine.getRuntimeService();
//任务管理
private static TaskService taskService = processEngine.getTaskService();
//管理流程定义
private static RepositoryService repositoryService = processEngine.getRepositoryService();
//历史管理(执行完的数据的管理)
private static HistoryService historyService = processEngine.getHistoryService();
//组织机构管理
private static IdentityService identityService =
processEngine.getIdentityService();
/**
* 发布流程
*
* @param processName 流程名称
* @param processClasspath 流程图的classPath
* @return
* @throws Exception
*/
public static Deployment releaseProcess(String processName, String processClasspath) {
Deployment deploy = repositoryService.createDeployment().name(processName).addClasspathResource(processClasspath).deploy();
System.out.println("发布的流程ID:" + deploy.getId() + "发布的流程名称:" + deploy.getName());
return deploy;
}
/**
* 查询整个流程的状态
*
* @param deploymentId 流程实例ID
* @throws Exception
*/
public static ProcessInstance queryProcessStatus(String deploymentId) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().deploymentId(deploymentId).singleResult();
if (!ObjectUtils.isEmpty(processInstance)) {
System.out.println("此流程在:" + processInstance.getActivityId() + "节点");
} else {
System.out.println("流程已结束!");
}
return processInstance;
}
/**
* 删除流程定义
*
* @param deploymentId 流程实例ID
* @param isDelete 是否级联删除
* @throws Exception
*/
public static void deleteProcess(String deploymentId, boolean isDelete) {
if (isDelete == true) {
//级联删除 删除当前规则下的所以信息,包括正在执行的和历史的信息
repositoryService.deleteDeployment(deploymentId, true);
} else {
// 普通删除 如果当前规则下有正在执行的流程,则抛出异常
repositoryService.deleteDeployment(deploymentId);
}
}
/**
* 启动流程
*
* @param processTemplate 流程模板名称
* @param starter 流程启动人
* @param processInstanceName 流程实例名称
* @param parameter 参数
*/
public static ProcessInstance startProcess(String processTemplate, String starter, String processInstanceName, Map<String, Object> parameter) {
Map<String, Object> map = new HashMap<>();// 参数
map.put("user", starter);
// 将变量存入map中
if (parameter != null) {
parameter.forEach((key, value) -> {
map.put(key, value);
});
}
identityService.setAuthenticatedUserId(starter);// 设置流程发起人START_USER_ID_
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processTemplate, map);
runtimeService.setProcessInstanceName(processInstance.getProcessInstanceId(), processInstanceName);
return processInstance;
}
/**
* 执行任务
*
* @param taskId 任务实例id
* @param parameter 参数
*/
public static Boolean next(String taskId, Map<String, Object> parameter) {
if (parameter == null) {
taskService.complete(taskId);
} else {
taskService.complete(taskId, parameter);
}
return true;
}
/**
* 启动流程并执行下一步
*
* @param processTemplate 流程模板名称
* @param starter 流程启动人
* @param processInstanceName 流程实例名称
* @param parameter 下一节点参数
*/
public static String startAndDoNext(String processTemplate, String starter, String processInstanceName, Map<String, Object> parameter) {
ProcessInstance processInstance = startProcess(processTemplate, starter, processInstanceName, null);
List<Task> list = getTaskInstenceByPIID(processInstance.getProcessInstanceId());
next(list.get(0).getId(), parameter);
return processInstance.getProcessInstanceId();
}
/**
* 查询个人任务列表
*
* @param assignee 个人名称/ID
* @return
* @throws Exception
*/
public static List<Task> queryMyTaskList(String assignee) {
// List<Task> list = taskService.createTaskQuery().taskAssignee(assignee).orderByTaskCreateTime().desc().list();
List<Task> list = taskService.createTaskQuery().taskCandidateOrAssigned(assignee).orderByTaskCreateTime().desc().list();
for (Task task : list) {
System.out.println("任务ID:" + task.getId() + ",");
System.out.println("任务名称:" + task.getName() + ",");
System.out.println("创建时间:" + task.getCreateTime() + ",");
System.out.println("任务属于:" + task.getAssignee());
}
return list;
}
/**
* 根据流程实例ID查询任务
*
* @param deploymentId
* @return
*/
public static List<Task> queryTaskByDLId(String deploymentId) {
List<Task> list = taskService.createTaskQuery().deploymentId(deploymentId).orderByTaskCreateTime().desc().list();
for (Task task : list) {
System.out.println("任务ID:" + task.getId() + ",");
System.out.println("任务名称:" + task.getName() + ",");
System.out.println("创建时间:" + task.getCreateTime() + ",");
System.out.println("任务属于:" + task.getAssignee());
}
return list;
}
/**
* 认领任务(申领)
*
* @param taskId 任务实例id
* @param userId 申领人id
*/
public static JSONObject claim(String taskId, String userId) {
JSONObject result = new JSONObject();
try {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task != null) {
if (task.getAssignee() == null || task.getAssignee().isEmpty()) {
// 进行申领
taskService.claim(taskId, userId);
result.put("status", 200);
result.put("message", "申领成功");
} else if (task.getAssignee().equals(userId)) {
result.put("status", 200);
result.put("message", "节点已申领");
} else {
result.put("status", -1);
result.put("message", "节点已被他人申领");
}
} else {
// 判断流程节点是否存在
List<HistoricIdentityLink> list = historyService.getHistoricIdentityLinksForTask(taskId);
if (list != null && list.size() > 0) {
result.put("status", -1);
result.put("message", "节点已流转");
}
}
} catch (ActivitiObjectNotFoundException e) {
e.printStackTrace();
result.put("status", -1);
result.put("message", "节点不存在");
} catch (Exception e) {
e.printStackTrace();
result.put("status", -1);
result.put("message", "程序异常");
} finally {
return result;
}
}
/**
* 终止流程实例(终止流程)
*
* @param taskId 任务实例id
*/
public static Boolean deleteProcessInstance(String taskId) {
Boolean flag = true;
try {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "终止流程");
} catch (Exception e) {
e.printStackTrace();
flag = false;
} finally {
return flag;
}
}
/**
* 挂起流程实例
*
* @param piid 流程实例id
*/
public static Boolean suspendProcessInstance(String piid) {
Boolean flag = true;
try {
runtimeService.suspendProcessInstanceById(piid);
} catch (Exception e) {
e.printStackTrace();
flag = false;
} finally {
return flag;
}
}
/**
* 流程实例解除挂起
*
* @param piid 流程实例id
*/
public static Boolean activateProcessInstance(String piid) {
Boolean flag = true;
try {
runtimeService.activateProcessInstanceById(piid);
} catch (Exception e) {
e.printStackTrace();
flag = false;
} finally {
return flag;
}
}
/**
* activiti节点跳转
*
* @param processDefinitionId 流程定义id
* @param executionId 执行id
* @param activityId 当前节点活动id
* @param destinationActivityId 目标节点活动id
*/
public static Boolean jump(String processDefinitionId, String executionId, String activityId, String destinationActivityId) {
Boolean flag = true;
try {
Map<String, Object> params = new HashMap<>();
ReadOnlyProcessDefinition processDefinitionEntity = (ReadOnlyProcessDefinition) repositoryService.getProcessDefinition(processDefinitionId);
// 当前节点
ActivityImpl currentActivity = (ActivityImpl) processDefinitionEntity.findActivity(activityId);
// 目标节点
ActivityImpl destinationActivity = (ActivityImpl) processDefinitionEntity.findActivity(destinationActivityId);
processEngine.getManagementService().executeCommand(new JDJumpTaskCmd(executionId, destinationActivity, params, currentActivity));
} catch (Exception e) {
e.printStackTrace();
flag = false;
} finally {
return flag;
}
}
/**
* activiti节点跳转
*
* @param taskId 任务实例id
* @param destinationActivityId 目标节点活动id
*/
public static Boolean jump(String taskId, String destinationActivityId) {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
return jump(task.getProcessDefinitionId(), task.getExecutionId(), task.getTaskDefinitionKey(), destinationActivityId);
}
/**
* activiti活动回退至上一节点(1、第一个节点、并行网关节点、包括网关节点不能回退;2、节点只有一个上级节点时直接回退;3、节点有多个上级节点时,回退到最新任务实例节点)
*
* @param taskId 任务实例id
*/
public static JSONObject regression(String taskId) {
JSONObject result = new JSONObject();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
// 流程定义id
String processDefinitionId = task.getProcessDefinitionId();
// 当前节点
String activityId = task.getTaskDefinitionKey();
// 流程定义及走向信息
ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId);
List<ActivityImpl> activitiList = def.getActivities();
// 判断是否为不可回退节点(第一节点、并行网关接节点)
for (ActivityImpl activityImpl : activitiList) {
if ("startEvent".equals(activityImpl.getProperty("type"))) {
List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();//获取从某个节点出来的所有线路
for (PvmTransition tr : outTransitions) {
PvmActivity ac = tr.getDestination(); //获取线路的终点节点
if (activityId.equals(ac.getId())) {
// 当前节点为第一个节点,不能回退
result.put("status", 201);
result.put("message", "第一个节点,不能回退");
return result;
}
}
}
if ("parallelGateway".equals(activityImpl.getProperty("type")) || "inclusiveGateway".equals(activityImpl.getProperty("type"))) {
List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();//获取从某个节点出来的所有线路
for (PvmTransition tr : outTransitions) {
PvmActivity ac = tr.getDestination(); //获取线路的终点节点
if (activityId.equals(ac.getId())) {
// 并行网关节点,不能回退
result.put("status", 202);
result.put("message", "并行网关节点,不能回退");
return result;
}
}
}
}
// 执行id
String executionId = task.getExecutionId();
// 查询历史节点记录
List<HistoricActivityInstance> historyList = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.list();
List<String> returnableNodeId = getReturnableNodeId(activityId, new ArrayList<>(), activitiList);
if (returnableNodeId.size() == 1) {
// 只有一个上级节点,直接回退
if (jump(processDefinitionId, executionId, activityId, returnableNodeId.get(0))) {
result.put("status", 200);
result.put("message", "回退成功");
return result;
}
} else if (returnableNodeId.size() > 1) {
// 有多个上级节点
String destinationActivityId = null;
for (int i = historyList.size() - 1; i >= 0; i--) {
if (returnableNodeId.contains(historyList.get(i).getActivityId())) {
// 获取最新上级节点任务,执行回退
if (jump(processDefinitionId, executionId, activityId, historyList.get(i).getActivityId())) {
result.put("status", 200);
result.put("message", "回退成功");
return result;
}
}
}
}
result.put("status", 203);
result.put("message", "回退失败");
return result;
}
/**
* 判断流程此节点的上级节点(userTask类型节点)
*
* @param activitiId 当前活动id
* @param result 返回结果
* @param activitiList 流程定义信息
*/
private static List<String> getReturnableNodeId(String activitiId, List<String> result, List<ActivityImpl> activitiList) {
for (ActivityImpl activityImpl : activitiList) {
if ("userTask".equals(activityImpl.getProperty("type"))) {
List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();//获取从某个节点出来的所有线路
for (PvmTransition tr : outTransitions) {
PvmActivity ac = tr.getDestination(); //获取线路的终点节点
if (activitiId.equals(ac.getId())) {
result.add(activityImpl.getId());
}
}
} else {
List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();//获取从某个节点出来的所有线路
for (PvmTransition tr : outTransitions) {
PvmActivity ac = tr.getDestination(); //获取线路的终点节点
if (activitiId.equals(ac.getId())) {
result.addAll(getReturnableNodeId(activityImpl.getId(), new ArrayList<>(), activitiList));
}
}
}
}
return result;
}
/**
* 设置任务变量
*
* @param task 任务实例
* @param var 变量名称
* @param data 变量数据
*/
public void setTaskVariables(Task task, String var, Object data) {
taskService.setVariable(task.getId(), var, data);
}
}
public class JDJumpTaskCmd implements Command<Void> {
protected String executionId;
protected ActivityImpl desActivity;
protected Map<String, Object> paramvar;
protected ActivityImpl currentActivity;
public Void execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = Context.getCommandContext().getExecutionEntityManager();
// 获取当前流程的executionId,因为在并发的情况下executionId是唯一的。
ExecutionEntity executionEntity = executionEntityManager.findExecutionById(executionId);
executionEntity.setVariables(paramvar);
executionEntity.setEventSource(this.currentActivity);
executionEntity.setActivity(this.currentActivity);
// 根据executionId 获取Task
Iterator<TaskEntity> localIterator = Context.getCommandContext()
.getTaskEntityManager()
.findTasksByExecutionId(this.executionId).iterator();
while (localIterator.hasNext()) {
TaskEntity taskEntity = (TaskEntity) localIterator.next();
// 触发任务监听
taskEntity.fireEvent("complete");
// 删除任务的原因
Context.getCommandContext().getTaskEntityManager().deleteTask(taskEntity, "completed", false);
}
executionEntity.executeActivity(this.desActivity);
return null;
}
/**
* 构造参数 可以根据自己的业务需要添加更多的字段
* @param executionId
* @param desActivity
* @param paramvar
* @param currentActivity
*/
public JDJumpTaskCmd(String executionId, ActivityImpl desActivity, Map<String, Object> paramvar, ActivityImpl currentActivity) {
this.executionId = executionId;
this.desActivity = desActivity;
this.paramvar = paramvar;
this.currentActivity = currentActivity;
}
}