在一般的金融业务系统中,通常会有一个类似的场景。
在某个月的21号,财务需要针对公司或企业的金额进行一个做账的操作。
在做账的时候,不允许进行业务的审批处理操作,这些流程必须要进行暂停。
在做账完成后,需要恢复相应的业务操作,可以供操作者继续使用。
前面博客中也说到了工作流的部署、扭转、删除等操作方式。工作流的删除的确可以实现上面的业务需求,但是有一点,删除后工作流会被删除,如果需要唤醒并继续使用则会不行。
为了解决这些类似的问题,在activiti 中,提供有专门的流程暂停(挂起)与激活操作。
先写一个简单的例子,实现工作流的挂起。
一经挂起操作,工作流将不允许继续执行审批扭转等操作。
@Test
public void suspend(){
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
// 查询流程定义
ProcessDefinition singleResult = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("demo01")
.singleResult();
// 判断是否被挂起 如果被挂起 则让其激活;激活 则进行挂起操作
boolean suspended = singleResult.isSuspended();
System.out.println("singleResult.getId()==== "+singleResult.getId());
if(!suspended){
/**
* 激活 需要进行挂起操作
* 参数一:流程定义id
* 参数二:是否暂停
* 参数三:暂停时间
*/
repositoryService.suspendProcessDefinitionById(singleResult.getId(),
true,
null);
System.out.println("流程已挂起");
}
}
文件部署成功后,再进行启动操作,此时的流程实例必然是激活状态,所以上面的代码在执行后,会进入挂起操作流程中。测试运行并查看控制台打印信息。

挂起操作执行成功,表示当前该部署的流程的所有流程实例都将会不能执行。为了验证是否可以操作,再次执行以下流程的状态扭转方法。
任务状态的推进与状态的扭转,需要知道对应的任务id信息。所以需要先查询任务信息,再进行提交扭转。
/**
* 查询当前个人待执行的任务
*/
@Test
public void viewReDoTask(){
// 工作流从启动开始 就会流转至 第一个 UserTask 节点,
// 此时可以通过配置的 Assignee 查询指定的人的 一些待处理 任务信息
String assignee = "worker";
// 数据库连接配置操作
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
// 根据对应的流程 查询当前指定人的待处理任务信息
TaskService taskService = defaultProcessEngine.getTaskService();
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey("demo01") // 指定哪个流程图模板
.taskAssignee(assignee) // 指定是谁负责待处理的任务
.list();
if(!CollectionUtil.isEmpty(list)){
list.forEach(x->{
System.out.println("流程实例 id "+x.getProcessInstanceId());
System.out.println("任务 id "+x.getId());
System.out.println("任务负责人 "+x.getAssignee());
System.out.println("任务名称 "+x.getName());
System.out.println("===========================================");
});
}
}

再次执行扭转操作,如果扭转失败,则表示activiti能够很好地控制挂起操作。
/**
* 工作流的节点与状态的扭转
*/
@Test
public void doTask(){
// 获取数据库的连接信息
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
// 完成当前节点的任务 并向下推进
String taskId = "2505";
taskService.complete(taskId);
}

上面的代码逻辑成功地将流程进行了挂起操作,后续某一天财务统计资金完成,需要开放给操作者继续使用。
@Test
public void actProcess(){
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
// 查询流程定义
ProcessDefinition singleResult = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("demo01")
.singleResult();
// 判断是否被挂起 如果被挂起 则让其激活;激活 则进行挂起操作
boolean suspended = singleResult.isSuspended();
System.out.println("singleResult.getId()==== "+singleResult.getId());
if(suspended){
/**
* 挂起 进行激活操作
* 参数一:流程定义id
* 参数二:是否激活
* 参数三:激活时间
*/
repositoryService.activateProcessDefinitionById(singleResult.getId(),
true,
null);
System.out.println("流程激活成功");
}
}
执行上述的代码,查看控制台日期信息。

再次进行流程的审批扭转操作,查看任务是否能够再次进行推进操作。

未出现报错信息,表示当前的流程得到了激活,并能继续进行工作流的审批操作了!
上面的案例中,是依据已部署的流程模板,同时暂停全部的对应实例与激活操作。但如果业务中出现需要针对某一个申请做暂停,其他流程实例依据进行审批流程,那么上面的方式则不能很好的去实现。
比如:张三的请假流程申请,需要做暂停;但其他李四、王五等人的请假流程不需要做管控等。
比如针对当前的审批模板,开启了两个流程实例。
select * from act_ru_execution;

当然,也可以用代码查询,如下:

2501流程已经被woeker做了扭转,此时在manager节点上;7501只是才开始流程,需要worker角色去处理。
如何只对2501限制审批流程处理,但7501能够正常执行呢?下面看代码。
/**
* 指定流程实例的暂停与激活
*/
@Test
public void oneSuppendAndAct(){
// 获取数据库的连接信息
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
ProcessInstance singleResult = runtimeService.createProcessInstanceQuery()
.processInstanceId("2501")
.singleResult();
// 当前实例流程对象是都被暂停
boolean suspended = singleResult.isSuspended();
// 流程定义id
String id = singleResult.getId();
if(suspended){
// 被暂停 则进行激活操作
runtimeService.activateProcessInstanceById(id);
System.out.println("流程定义:"+id+",已激活");
}else{
// 是激活状态 则进行暂停
runtimeService.suspendProcessInstanceById(id);
System.out.println("流程定义:"+id+",已挂起");
}
}
最开始2501是正常的,并且已经被worker进行了处理。执行上述的代码逻辑后,因为监测到是激活状态,所以执行了挂起。
按道理来说,
2501进行了挂起,但必须要求同部署模板下的其他流程实例能够正常执行。
现在执行7501的流程推进,查看效果。

执行推进操作。

没有报错,查看当前流程信息。

推进是成功的,最新状态已经到了部门经理审批。
现在再来验证2501是否能够被推进。

得到2501流程实例此时部门经理审批的任务id为5002。进行流程的推进操作。

【结论】
流程能够对指定的实例对象进行管控!!
将2501实例对应的当前任务5002进行恢复激活操作,再次进行推进。



【结论】
激活后的指定实例对象,能够进行审批操作和状态的扭转。