文章目录
- 一、定时器
- 1. 流程定义定时激活
- 2. 流程实例定时挂起
- 3. 定时任务执行过程
- ServiceTask 服务任务
- 委托表达式
- 表达式
- 类中字段
- ScriptTask 脚本任务
- JS TASK
一、定时器
相关知识链接阅读:事件网关——定时器启动事件
1. 流程定义定时激活
可以通过activateProcessDefinitionsOn(date)
给流程定义设置一个启动时间。这个流程就会延迟激活。在激活之前,无法启动该流程。
- 部署流程
@Test
void test_delayDeploy() {
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("process/请假Demo.bpmn20.xml")
.name("deployName-定时启动")
// 表示延迟1分钟激活流程定义
.activateProcessDefinitionsOn(new Date(System.currentTimeMillis() + 1000 * 60))
.key("deployKey-dsqd").deploy();
System.out.println("deploy.getId() = " + deploy.getId());
}
- 启动测试
@Test
void startFlow(){
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROC_KEY);
System.out.println("processInstance.getId() = " + processInstance.getId());
}
当我们在流程定义还未到时激活的时候,来启动一个流程,则会抛出异常:流程定义挂起
org.flowable.common.engine.api.FlowableException: Cannot start process instance. Process definition 请假Demo (id = qj-demo:1:d91875ee-a88c-11ed-a56b-c83dd4896099) is suspended
我们查看ACT_RU_TIMER_JOB
表,可以看到表中有一条任务记录,其中DUEDATE_
是处理时间(当时间到达或超过自动处理,会将ACT_RE_PROCDEF
表的SUSPENSION_STATE_
状态2变更为1), HANDLER_TYPE_
是激活流程定义,HANDLER_CFG_
是否包含流程实例。
2. 流程实例定时挂起
@Test
void test_Suspend() throws InterruptedException {
// 设置30秒后自动挂起该流程定义与流程实例
Date suspensionDate = new Date(System.currentTimeMillis() + 1000 * 30);
// 这个方法是挂起流程定义的方法
repositoryService.suspendProcessDefinitionByKey(PROC_KEY, true, suspensionDate);
// 这个方法是流程实例的挂起方法
// runtimeService.suspendProcessInstanceById("id001");
Thread.sleep(30);
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY).latestVersion().singleResult();
System.out.println("processDefinition.getName() = " + processDefinition.getName());
System.out.println("processDefinition.isSuspended() = " + processDefinition.isSuspended());
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processDefinitionKey(PROC_KEY).list();
for (ProcessInstance instance : list) {
System.out.println("instance.isSuspended() = " + instance.isSuspended());
}
}
3. 定时任务执行过程
ManagementService方法名 | 作用 | 涉及表变动 |
---|---|---|
moveTimerToExecutableJob(job.getId()); | 将定时任务移动到执行 | ACT_RU_TIMER_JOB -> ACT_RU_JOB |
moveJobToDeadLetterJob(job.getId()); | 将任务移动到死信任务 | ACT_RU_TIMER_JOB -> ACT_RU_DEADLETTER_JOB |
`moveDeadLetterJobToExecutableJob(job.getId(), 1) | 移动死信任务到执行任务 | ACT_RU_DEADLETTER_JOB -> ACT_RU_JOB |
createTimerJobQuery() | 查询定时任务 | ACT_RU_TIMER_JOB |
createDeadLetterJobQuery() | 查询死信任务 | ACT_RU_DEADLETTER_JOB |
任务相关表信息
表名 | 含义 |
---|---|
ACT_RU_TIMER_JOB | 定时作业表 |
ACT_RU_JOB | 运行时作业表(进入运行时作业表的任务会被立即执行) |
ACT_RU_HISTORY_JOB | 历史作业表 |
ACT_RU_DEADLETTER_JOB | 死信作业表(DeadLetter:死信、退件、空文,存放取消的定时作业) |
ACT_RU_SUSPENDED_JOB | 挂起作业表 |
ACT_RU_EXTERNAL_JOB | 外部作业表 |
/**
* 延迟5分钟激活
*
* @throws InterruptedException
*/
@Test
void test_activeProcess() throws InterruptedException {
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY)
.latestVersion().singleResult();
// 延迟5分钟激活流程定义与实例
Date activationDate = new Date(System.currentTimeMillis() + 5 * 60 * 1000);
System.out.println("pd.isSuspended() = " + pd.isSuspended());
if (!pd.isSuspended()) {
repositoryService.suspendProcessDefinitionById(pd.getId());
}
repositoryService.activateProcessDefinitionById(pd.getId(), true, activationDate);
//org.flowable.common.engine.api.FlowableException: Cannot set suspension state 'suspended' for ProcessDefinitionEntity[qj-demo:1:d91875ee-a88c-11ed-a56b-c83dd4896099]': already in state 'suspended'.
}
/**
* 查询并立即激活
*
* @throws InterruptedException
*/
@Test
void queryAndActiveNow() throws InterruptedException {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY)
.latestVersion().singleResult();
System.out.println("processDefinition.isSuspended() = " + processDefinition.isSuspended());
List<Job> list = managementService.createTimerJobQuery().processDefinitionId(processDefinition.getId()).list();
list.forEach(job -> {
managementService.moveTimerToExecutableJob(job.getId());
});
Thread.sleep(30);
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY)
.latestVersion().singleResult();
System.out.println("pd.isSuspended() = " + pd.isSuspended());
}
/**
* 延迟5分钟挂起
*
* @throws InterruptedException
*/
@Test
void test_suspendedProcess() throws InterruptedException {
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY)
.latestVersion().singleResult();
// 延迟5分钟激活流程定义与实例
Date activationDate = new Date(System.currentTimeMillis() + 2 * 60 * 1000);
System.out.println("pd.isSuspended() = " + pd.isSuspended());
if (pd.isSuspended()) {
repositoryService.activateProcessDefinitionById(pd.getId());
}
repositoryService.suspendProcessDefinitionById(pd.getId(), true, activationDate);
}
/**
* 查询并立即挂起
*
* @throws InterruptedException
*/
@Test
void queryAndSuspendedNow() throws InterruptedException {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY)
.latestVersion().singleResult();
System.out.println("processDefinition.isSuspended() = " + processDefinition.isSuspended());
// 定时任务查询
List<Job> list = managementService.createTimerJobQuery().processDefinitionId(processDefinition.getId()).list();
list.forEach(job -> {
managementService.moveJobToDeadLetterJob(job.getId());
});
Thread.sleep(60 * 1000);
// deadLetter 死信、空文、退件
// 从退件任务队列查询
List<Job> deadLetterJobs = managementService.createDeadLetterJobQuery().processDefinitionId(processDefinition.getId()).list();
deadLetterJobs.forEach(job -> {
// 将退件任务移到执行列表
managementService.moveDeadLetterJobToExecutableJob(job.getId(), 1);
// managementService.moveDeadLetterJobToHistoryJob(job.getId(),1);
});
Thread.sleep(60 * 1000);
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(PROC_KEY)
.latestVersion().singleResult();
System.out.println("pd.isSuspended() = " + pd.isSuspended());
}
ServiceTask 服务任务
ServiceTask一般由系统自动完成,当系统走到这一步的时候,不会停下,会自动执行我们在ServiceTask配置的方法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/e04fdfc226ca495091933b45ec8ad241.png
委托表达式
实现了JavaDelegate的接口,注入Spring容器,在配置中可以不写完整类名,只需要写Spring容器名称即可。首字母小写${myServiceTask}
@Component
public class MyServiceTask implements JavaDelegate {
@Autowired
TaskService taskService;
@Autowired
RuntimeService runtimeService;
@Override
public void execute(DelegateExecution execution) {
System.out.println("========MyServiceTask2==========");
System.out.println("execution = " + execution);
// execution.getCurrentActivityId()
}
}
表达式
表达式可以是普通类中的一个方法${myServiceTask2.hello()}
类中字段
Expression userName;
@Override
public void execute(DelegateExecution execution) {
System.out.println("========MyServiceTask2==========");
System.out.println("execution = " + execution);
if (userName != null) {
System.out.println("username.getExpressionText() = " + userName.getExpressionText());
System.out.println("username.getValue(execution) = " + userName.getValue(execution));
}
}
ScriptTask 脚本任务
脚本任务,当流程到达该节点的时候,自动执行脚本。可以有JS(JavaScript)、Groovy、Juel脚本。
JS TASK
需要注意的是JS脚本不支持ES6语法。
部署流程
@Test
void doDeploy2() {
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("process/脚本任务demo.bpmn20.xml")
.deploy();
System.out.println("deploy.getId() = " + deploy.getId());
}
启动流程与查询流程变量
@Test
void jsTask() {
Map<String, Object> variables = new HashMap<>();
variables.put("a", 99);
variables.put("b", 98);
ProcessInstance pi = runtimeService.startProcessInstanceByKey("js-task", variables);
System.out.println("pi.getId() = " + pi.getId());
System.out.println("pi.getActivityId() = " + pi.getActivityId());
System.out.println("pi.getProcessVariables() = " + pi.getProcessVariables());
}