【二三方】_Quartz实现定时任务

Quartz实现定时任务

1.引入jar包

maven项目可以直接引入Quartz包:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz 定时任务管理工具quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>

如果是SpringBoot项目,则已经集成好了starter包,引入后启动项目,则会将相应Quartz类自动注入到Spring容器中,实现自动配置:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>

此处为学习Quartz使用原理,引入Quartz包。

2.创建任务类

实现Job接口并重写其execute方法,该方法即为需要定时执行的任务方法。

定时任务方法往往要使用到Spring容器中的bean,而Quartz的Job接口实现类中是无法通过@Autowired注入Spring Bean的,只有注入到Spring容器中去了的bean才能进行依赖注入。有一些方法可以解决这个问题,此处我们采用文末附件中的SpringUtil工具类来帮助我们获取Spring容器中的bean。

定时任务所需的一些参数也可以通过JobExecutionContext来传入。

1
2
3
4
5
6
7
8
9
10
11
public class ConsolePrintJob implements Job {

/**
* 定时任务即为:通过SpringUtil获取Spring容器中名为print的bean,并执行其中的printTime方法。
*/
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
ConsolePrint consolePrint = SpringUtil.getBean("print");
consolePrint.printTime();
}
}
3.创建定时任务调度器管理类

定时任务调度器可以写得很复杂,实现很多功能,此处只实现最基本的功能:

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
@Component
public class MyScheduler {

private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

/**
* 为一个调度器装载任务和触发器
*/
public Scheduler scheduleJob() throws SchedulerException {
//从工厂类中获取一个调度器实例
Scheduler scheduler = schedulerFactory.getScheduler();

//1.创建JobDetail,用于装载任务类
JobDetail jobDetail = JobBuilder.newJob(ConsolePrintJob.class).withIdentity("ConsolePrintJob","jingzhaoGroup").build();

//2.创建Cron表达式
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");

//3.创建CronTrigger触发器,用于根据Cron表达式设定定时任务出发时间
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withSchedule(cronScheduleBuilder).withIdentity("trigger1", "jingzhaoGroup").build();

//4.将成对的任务和触发器装载到任务调度器中;同一个任务调度器可以装载多对任务和触发器。
scheduler.scheduleJob(jobDetail, cronTrigger);

return scheduler;
}

/**
* 开启调度器
*/
public void startScheduleJob(Scheduler scheduler) throws SchedulerException {
scheduler.start();
}

/**
* 关闭调度器
*/
public void stopScheduleJob(Scheduler scheduler) throws SchedulerException {
scheduler.shutdown();
}
}
4.端口控制定时任务开关或设置项目启动自动开启定时任务

此处简单实现一下通过端口控制定时任务的开关:

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
@RestController
@RequestMapping("/schedule")
public class Switch {

@Autowired
MyScheduler myScheduler;

private static Scheduler scheduler = null;

@GetMapping("/open")
public String openSchedule() {
try {
scheduler = myScheduler.scheduleJob();
myScheduler.startScheduleJob(scheduler);
return "调度器开启成功!";
} catch (SchedulerException e) {
return "调度器开启异常!";
}
}

@GetMapping("/stop")
public String stopSchedule() {
try {
if (scheduler == null) {
return "定时任务调度器尚未开启!";
}
myScheduler.stopScheduleJob(scheduler);
return "访问成功!";
} catch (SchedulerException e) {
return "访问异常!";
}
}
}
附件:SpringUtil工具类
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
79
80
81
82
83
84
85
86
87
/**
* Spring 工具类
*/
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext context;

@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringUtil.context = context;
}

/**
* 获取 Spring Bean
*
* @param clazz 类
* @param <T> 泛型
* @return 对象
*/
public static <T> T getBean(Class<T> clazz) {
if (clazz == null) {
return null;
}
return context.getBean(clazz);
}

/**
* 获取 Spring Bean
*
* @param bean 名称
* @param <T> 泛型
* @return 对象
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String bean) {
if (bean == null) {
return null;
}
return (T) context.getBean(bean);
}

/**
* 获取 Spring Bean
*
* @param beanName 名称
* @param clazz 类
* @param <T> 泛型
* @return 对象
*/
public static <T> T getBean(String beanName, Class<T> clazz) {
if (null == beanName || "".equals(beanName.trim())) {
return null;
}
if (clazz == null) {
return null;
}
return (T) context.getBean(beanName, clazz);
}

/**
* 获取上下文
*
* @return 上下文
*/
public static ApplicationContext getContext() {
if (context == null) {
throw new RuntimeException("There has no Spring ApplicationContext!");
}
return context;
}

/**
* 发布事件
*
* @param event 事件
*/
public static void publishEvent(ApplicationEvent event) {
if (context == null) {
return;
}
try {
context.publishEvent(event);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}