spring-boot中quartz使用

spring-boot中quartz使用

1、maven项目中引入

在pom.xml中添加以下依赖

1
2
3
4
5
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>

2、使用

Quartz的3个重要组成,JobDetail,Trigger,Scheduler

  1. 创建一个类 HelloJob.java,这个类是编写我们的具体要实现任务(打印Hello Quartz)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloJob implements Job{
  public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前的执行时间 例如 2017-11-23 00:00:00
Date date = new Date();
//在job中可以获取设置的参数
String value = context.getJobDetail().getJobDataMap().get("param").toString();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("现在的时间是:"+ sf.format(date));
//具体的业务逻辑
System.out.println("Hello Quartz");
}
}
  1. 创建一个类HelloScheduler.java,这个是具体触发我们的任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {
//创建一个jobDetail的实例,将该实例与HelloJob Class绑定
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob").build();
//执行的任务中传入参数------------------------------
jobDetail.getJobDataMap().put("param", "value");
//创建一个Trigger触发器的实例,定义该job立即执行,并且每2秒执行一次,一直执行
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
//创建schedule实例
StdSchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail,trigger);
}
}
  1. 执行main方法

3、job类中注入service报错null解决办法

不能使用StdSchedulerFactory,需要自定义factory来获取Scheduler

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
package com.meimei.quartz_demo.factory;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

/**
* @author liuzhangmin
* @desc 自定义工厂类
* @date 2018-09-09
*/
@Component
public class SchedulerFactory extends AdaptableJobFactory {

//spring bean 对象管理工厂
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//自动注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}

相关配置

配置文件 :quartz.properties

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
# 固定前缀org.quartz
# 主要分为scheduler、threadPool、jobStore、plugin等部分
#
#
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.scheduler.wrapJobExecutionInUserTransaction=false

# 实例化ThreadPool时,使用的线程类为SimpleThreadPool
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool

# threadCount和threadPriority将以setter的形式注入ThreadPool实例
# 并发个数
org.quartz.threadPool.threadCount=5
# 优先级
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

org.quartz.jobStore.misfireThreshold=5000

# 默认存储在内存中(不需要配置 可以在源码中的properties中看到这个配置)
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

# ——————————————————————————————上面展示的是非持久的配置——————————————————————————

配置类:

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
package com.meimei.quartz_demo.config;

import com.meimei.quartz_demo.factory.SchedulerFactory;
import org.quartz.Scheduler;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.io.IOException;
import java.util.Properties;

/**
* @author licunzhi
* @desc quartz configuration(we can also use xml, but springboot recommend to use annotation @configuration to config)
* @date 2018-09-05
*/
@Configuration
public class QuartzConfiguration {

// 注入service需要配置工厂类
@Autowired
private SchedulerFactory schedulerFactory;

@Bean(name="SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// 注入service需要配置工厂类
factory.setJobFactory(schedulerFactory);
// 注入service需要配置工厂类

PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
Properties properties = propertiesFactoryBean.getObject();
factory.setQuartzProperties(properties);
return factory;
}

/*
* quartz初始化监听器
*/
@Bean
public QuartzInitializerListener executorListener() {
return new QuartzInitializerListener();
}

/*
* 通过SchedulerFactoryBean获取Scheduler的实例
*/
@Bean(name="Scheduler")
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}

}

这时使用配置好的工厂类获取的Scheduler,相应的job类中就可以注入service了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class HelloScheduler {

@Autowired
@Qualifier(value = "Scheduler")
Scheduler scheduler;

public static void main(String[] args) throws SchedulerException {
//创建一个jobDetail的实例,将该实例与HelloJob Class绑定
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("myJob").build();
//执行的任务中传入参数------------------------------
jobDetail.getJobDataMap().put("param", "value");
//创建一个Trigger触发器的实例,定义该job立即执行,并且每2秒执行一次,一直执行
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
//使用自定义工厂获取的Scheduler实例
// StdSchedulerFactory factory = new StdSchedulerFactory();
// Scheduler scheduler = factory.getScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail,trigger);
}
}