<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
#属性配置文档 https://github.com/quartz-scheduler/quartz/blob/master/docs/configuration.adoc
spring:
#配置数据源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sgrain?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: root
password: smallgrain
quartz:
#持久化到数据库方式
job-store-type: jdbc
#quartz调度程序属性
properties:
org:
quartz:
scheduler:
#调度任务实例名称,如果是集群则每个实例必须是相同的名字
instanceName: SmallGrainScheduler
#实例ID,对于集群中工作的所有调度器必须是唯一的,如果值是AUTO则会自动生成,如果希望值来自系统属性则设置为SYS_PROP
instanceId: AUTO
jobStore:
#job、traggers、calendars持久化实现类,默认:org.quartz.simpl.RAMJobStore
class: org.quartz.impl.jdbcjobstore.JobStoreTX
#调度程序下次触发时间的毫秒数,默认是60000(60 seconds)
misfireThreshold: 60000
#驱动程序代理类
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#表名前缀,默认:QRTZ_
tablePrefix: QUATRZ_
#默认:false,设置JDBCJobStore的JobDataMaps中存储的是字符串类型的key-value,否则为 true
useProperties: false
#设置为true以启用集群功能,如果Quartz的多个实例使用同一组数据库表,则必须将此属性设置为true,否则将遇到严重的破话,默认:false
isClustered: true
#设置此实例与集群的其它实例"checks-in"的频率(毫秒),影响实例的检测失败速率,默认:15000
clusterCheckinInterval: 10000
#配置线程池
threadPool:
#要使用的线程池实心名称,与Quartz自带的线程池应该可以满足几乎每个用户的需求,它的行为非常简单,而且已经过很好的测试,它提供了一个固定大小的线程池,这些线程在调度程序的生存期内"生存"
class: org.quartz.simpl.SimpleThreadPool
#线程数
threadCount: 10
#线程优先级,可以是Thread.MIN_PRIORITY(1)和Thread.MAX_PRIORITY(10)之间的数据,默认是:Thread.NORM_PRIORITY (5)
threadPriority: 5
#可以设置为true以将线程池中的线程创建为守护程序线程。默认:false
makeThreadsDaemons: false
#线程池中线程名的前缀,默认:MyScheduler_Worker
threadNamePrefix: MyScheduler_Worker
#默认true
threadsInheritGroupOfInitializingThread: true
#默认true
threadsInheritContextClassLoaderOfInitializingThread: true
jdbc:
initialize-schema: always
#初始化数据库脚本路径,默认使用classpath:org/quartz/impl/jdbcjobstore/tables_@@platform@@.sql路径下的脚本
schema: classpath:tables_mysql.sql
上述quartz集成到springboot的配置注解已经写的很清楚了,现在就对schema配置的sql脚本做一个解释,默认情况下jar包中自带的有对应的各种数据库的脚本,不需要配置根据数据源的不同自动选择脚本进行初始化,如果需要更改表的前缀名称那么可以将其拷贝出来放到classpath下;脚本在jar包中的位置注释中已经写了,可以自己查看;
import com.sgrain.boot.common.enums.DateFormatEnum;
import com.sgrain.boot.common.utils.date.DateUtils;
import com.sgrain.boot.common.utils.json.JSONUtils;
import com.sgrain.boot.web.httpclient.HttpClientService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.Date;
import java.util.Map;
/**
* @program: spring-parent
* @description:
* @create: 2020/08/28
*/
public class ThreadPoolJob extends QuartzJobBean {
@Autowired
private HttpClientService httpClientService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
Trigger trigger = context.getTrigger();
String valeu = context.getTrigger().getJobDataMap().getString("tragger_param");
String jobValue = context.getJobDetail().getJobDataMap().getString("jobDataKey");
System.out.println(JSONUtils.toJSONPrettyString(context.getMergedJobDataMap()));
System.out.println(Thread.currentThread().getName() + "--执行作业调度--" + DateUtils.formatDate(new Date(), DateFormatEnum.YYYY_MM_DD_HH_MM_SS.getFormat())+"--"+valeu+"--"+jobValue);
}
}
package com.sgrain.boot.quartz.config;
import com.sgrain.boot.quartz.job.ThreadPoolJob;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @program: spring-parent
* @description:
* @create: 2020/08/28
*/
@Configuration(proxyBeanMethods = false)
public class QuartzConfig {
@Bean
public JobDetail jobDetail(){
JobDetail jobDetail = JobBuilder.newJob(ThreadPoolJob.class)
//是否持久化
.storeDurably(true)
.withDescription("Job任务描述")
//任务名称和任务分组 组合成任务唯一标识
.withIdentity(JobKey.jobKey("JobName", "JobGroup"))
.usingJobData("jobDataKey", "jobDataValue")
.build();
return jobDetail;
}
@Bean
public Trigger trigger(JobDetail jobDetail){
Trigger trigger = TriggerBuilder.newTrigger() //创建一个定义或者构建触发器的builder实例
.forJob(jobDetail) //通过从给定的作业中提取出jobKey,设置由生成的触发器触发的作业的标识
//自定义触发器描述
.withDescription("自定义触发器描述")
//设置触发器名称、触发器分组,组合为触发器唯一标识
.withIdentity(TriggerKey.triggerKey("traggerName", "traggerGroup"))
//如果有一个Job任务供多个触发器调度,而每个触发器调度传递不同的参数,此时JobDataMap可以提供不同的数据输入
//在任务执行时JobExecutionContext提供不同的JobDataMap参数给Job
.usingJobData("tragger_param", "tragger_value")
//触发器优先级
.withPriority(6)
//设置用于定义触发器的{@link org.quartz.ScheduleBuilder}配置计划
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? "))
//将触发器的启动时间设置为当前时刻,触发器可能此时触发,也可能不触发,这取决于为触发器配置的计划
.startNow()
//构造触发器
.build();
return trigger;
}
}
在上述示例中对Trigger和JobDetials都有对JobDataMap属性的设置usingJobData,那么usingJobData的作用是什么呢?其实我们看下其源码的注释就会很清楚了:
/**
* Holds state information for Job
instances.
*
*
* JobDataMap
instances are stored once when the Job
* is added to a scheduler. They are also re-persisted after every execution of
* jobs annotated with @PersistJobDataAfterExecution
.
*
*
*
* JobDataMap
instances can also be stored with a
* Trigger
. This can be useful in the case where you have a Job
* that is stored in the scheduler for regular/repeated use by multiple
* Triggers, yet with each independent triggering, you want to supply the
* Job with different data inputs.
*
*
*
* The JobExecutionContext
passed to a Job at execution time
* also contains a convenience JobDataMap
that is the result
* of merging the contents of the trigger's JobDataMap (if any) over the
* Job's JobDataMap (if any).
*
*
*
* Update since 2.2.4 - We keep an dirty flag for this map so that whenever you modify(add/delete) any of the entries,
* it will set to "true". However if you create new instance using an exising map with {@link #JobDataMap(Map)}, then
* the dirty flag will NOT be set to "true" until you modify the instance.
*
*
* @see Job
* @see PersistJobDataAfterExecution
* @see Trigger
* @see JobExecutionContext
*
* @author James House
*/
解释一下首先是存储Job任务实例的信息,当Job任务添加到调度任务时JobDataMap会被持久化存储;在Job类上添加@PersistJobDataAfterExecution注解在任务执行完成后也会重新持久化;
JobDataMap实例也可以通过Trigger一起存储,当有一个Job被多个触发器调用时,每个触发器可以传递不同的参数给Job任务;
Job任务可以通过JobExecutionContext接收到JobDataMap中存储的数据,可以通过getMergedJobDataMap合并的方法获取到存储在JobDetails和Trigger中的数据,也可以分别获取存储在Trigger和JobDetails中的数据。
GitHub源码:https://github.com/mingyang66/spring-parent/tree/master/sgrain-spring-boot-quartz