一个人有无成就,决定于他青年时期是不是有志气。——谢觉哉

分享一个自己写的Quartz工具类,可以轻松实现倒计时功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import cn.hutool.core.date.DateUtil;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.dromara.streamquery.stream.core.collection.Lists;
import org.quartz.*;
import org.quartz.core.jmx.JobDataMapSupport;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;

@UtilityClass
public class QuartzUtil {

@SneakyThrows
public static Scheduler startTaskAt(LocalDateTime time, JobKey jobKey,
Map<String, Object> jobDataMap, Class<? extends Job> jobClazz) {
var scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.deleteJob(jobKey);
var jobDetail = JobBuilder.newJob().ofType(jobClazz).withIdentity(jobKey)
.usingJobData(JobDataMapSupport.newJobDataMap(jobDataMap)).build();
var trigger = TriggerBuilder.newTrigger().withIdentity(jobKey.getName(), jobKey.getGroup())
.startAt(DateUtil.date(time)).build();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
return scheduler;
}

public static Scheduler startTaskTimeSeconds(Long timeSeconds, JobKey jobKey,
Map<String, Object> jobDataMap, Class<? extends Job> jobClazz) {
try {
var scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.deleteJob(jobKey);
var jobDetail = JobBuilder.newJob().ofType(jobClazz).withIdentity(jobKey)
.usingJobData(JobDataMapSupport.newJobDataMap(jobDataMap)).build();
var trigger = TriggerBuilder.newTrigger()
.withIdentity(jobKey.getName(), jobKey.getGroup())
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(timeSeconds.intValue()))
.startNow().build();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
return scheduler;
} catch (SchedulerException e) {
throw new ApiServerException(e);
}
}


public static void deleteJob(JobKey readyStartJobKey) {
try {
var scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.deleteJob(readyStartJobKey);
} catch (SchedulerException e) {
throw new ApiServerException(e);
}
}

public static void deleteJobs(String groupName) {
try {
var scheduler = StdSchedulerFactory.getDefaultScheduler();
Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.groupEquals(groupName));
scheduler.deleteJobs(Lists.ofColl(jobKeys));
} catch (SchedulerException e) {
throw new ApiServerException(e);
}
}

public static void pauseJob(JobKey key) {
try {
var scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.pauseJob(key);
} catch (SchedulerException e) {
throw new ApiServerException(e);
}
}
}

对应的单元测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import lombok.SneakyThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

class QuartzUtilTest {

@Test
@SneakyThrows
@Disabled("sleep")
void startTaskAtTest() {
var obj = new AtomicInteger();
Map<String, Object> map = Map.of("test", obj);
var jobKey = JobKey.jobKey("startTaskAtTest", "test");
var time = LocalDateTime.now().plus(Duration.ofSeconds(3));
QuartzUtil.startTaskAt(time, jobKey, map, StartTaskAtTestJob.class);
TimeUnit.SECONDS.sleep(4);
Assertions.assertEquals(1, obj.get());
}

@Test
@SneakyThrows
@Disabled("sleep")
void startTaskTimeSecondsTest() {
var obj = new AtomicInteger(3);
Map<String, Object> map = Map.of("countdown", obj);
var jobKey = JobKey.jobKey("startTaskTimeSecondsTest", "test");
QuartzUtil.startTaskTimeSeconds(3L, jobKey, map, StartTaskTimeSecondsTestJob.class);
TimeUnit.SECONDS.sleep(4);
Assertions.assertEquals(0, obj.get());
}

public static class StartTaskAtTestJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
var jobDataMap = context.getMergedJobDataMap();
var test = jobDataMap.get("test");
if (test instanceof AtomicInteger obj) {
obj.set(1);
}
}
}

public static class StartTaskTimeSecondsTestJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
var jobDataMap = context.getMergedJobDataMap();
var countdown = jobDataMap.get("countdown");
if (countdown instanceof AtomicInteger obj) {
obj.set(obj.decrementAndGet());
}
}
}

}