Quartz(5-SpringBoot整合)
|总字数:2.9k|阅读时长:11分钟|浏览量:|
单机版配置
依赖
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> <version>2.3.12.RELEASE</version> </dependency>
|
任务创建
1 2 3 4 5 6 7 8 9 10 11 12
|
public class TestJob extends QuartzJobBean {
private static final Log logger = LogFactory.getLog(TestJob.class);
@Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { logger.info("测试======"); } }
|
- 可以实现Job接口,也可以继承QuartzJobBean
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
|
@Configuration public class QuartzConfig {
@Bean public JobDetail jobDetail() { return JobBuilder.newJob(TestJob.class) .withIdentity("testJob") .withDescription("testJob") .storeDurably() .build(); }
@Bean public Trigger trigger() { return TriggerBuilder.newTrigger() .forJob(jobDetail()) .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)) .build(); } }
|
- 项目初始化手动创建任务
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
| @Component public class JobInit implements ApplicationRunner {
private static final String ID = "SUMMERDAY";
@Autowired private Scheduler scheduler;
@Override public void run(ApplicationArguments args) throws Exception { JobDetail jobDetail = JobBuilder.newJob(TestJob.class) .withIdentity(ID + " 01") .storeDurably() .build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"); Trigger trigger = TriggerBuilder.newTrigger() .forJob(jobDetail) .withIdentity(ID + " 01Trigger") .withSchedule(scheduleBuilder) .startNow() .build(); scheduler.scheduleJob(jobDetail, trigger); } }
|
yaml配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| spring: quartz: job-store-type: memory auto-startup: true startup-delay: 0 wait-for-jobs-to-complete-on-shutdown: true overwrite-existing-jobs: false properties: org: quartz: threadPool: threadCount: 25 threadPriority: 5 class: org.quartz.simpl.SimpleThreadPool
|
持久化配置
集群部署
一个Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点。这就意味着你必须对每个节点分别启动或停止。Quartz集群中,独立的Quartz节点并不与另一其的节点或是管理节点通信,而是通过同一个数据库表来感知到另一Quartz应用的。因为Quartz集群依赖于数据库,所以必须首先创建Quartz数据库表,Quartz发布包中包括了所有被支持的数据库平台的SQL脚本。
创建数据库表
针对不同的数据库,org.quartz.impl.jdbcjobstore 包下提供了不同建表脚本,数据库脚本放在org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar!包中的\org\quartz\impl\jdbcjobstore路径下
表名 |
描述 |
qrtz_fired_triggers |
存储已触发的trigger相关信息 |
qrtz_paused_trigger_grps |
存储已暂停的trigger组信息 |
qrtz_scheduler_state |
存储Scheduler状态信息 |
qrtz_locks |
存储悲观锁的信息 |
qrtz_simple_triggers |
存储Simple trigger信息 |
qrtz_simprop_triggers |
存储其他几种trigger信息 |
qrtz_cron_triggers |
存储cron trigger信息 |
qrtz_blob_triggers |
blog类型存储triggers |
qrtz_triggers |
存储已配置的trigger信息 |
qrtz_job_details |
存储每一个已配置的job details |
qrtz_calendars |
以blog类型存储Calendar信息 |
所有的表中都含有一个SCHED_NAME字段,对应我们配置的scheduler-name,相同Scheduler-name的节点,形成一个Quartz集群
存储类型
Quartz提供两种基本作业存储类型:RAMJobStore和JDBC作业存储。在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。
类型 |
优点 |
缺点 |
RAMJobStore |
不要外部数据库,配置容易,运行速度快 |
因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。另外因为存储到JVM内存里面,所以可以存储多少个Job和Trigger将会受到限制 |
JDBC作业存储 |
支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务 |
运行速度的快慢取决与连接数据库的快慢 |
事务管理类型
类型 |
描述 |
JobStoreTX |
如果不需要将调度命令(例如添加和删除triggers)绑定到其他事务,那么可以通过使用 JobStoreTX 管理事务(这是最常见的选择) |
JobStoreCMT |
如果需要 Quartz 与其他事务(即J2EE应用程序服务器)一起工作,那么应该使用 JobStoreCMT,这种情况下,Quartz 将让应用程序服务器容器管理事务 |
1 2 3
|
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
|
数据库驱动代理
针对不同的数据库制作了不同的数据库的代理,其中使用最多的是 StdJDBCDelegate ,它是一个使用 JDBC 代码(和SQL语句)来执行其工作的委托。其他驱动代理可以在 “org.quartz.impl.jdbcjobstore” 包或其子包中找到。如 DB2v6Delegate(用于DB2版本6及更早版本),HSQLDBDelegate(HSQLDB),MSSQLDelegate(SQLServer),PostgreSQLDelegate(PostgreSQL),WeblogicDelegate(用于使用Weblogic创建的JDBC驱动程序)
1
| org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> <version>2.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.12.RELEASE</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency>
|
- yaml配置
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
| spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/quartz?serverTimezone=GMT%2B8 username: root password: 123456 quartz: job-store-type: jdbc scheduler-name: hyhScheduler wait-for-jobs-to-complete-on-shutdown: true jdbc: initialize-schema: never properties: org: quartz: startup-delay: 60 overwrite-existing-jobs: false scheduler: instanceId: AUTO instanceName: hyhScheduler jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate tablePrefix: QRTZ_ isClustered: true clusterCheckinInterval: 1000 useProperties: false misfireThreshold: 60000 threadPool: threadCount: 25 threadPriority: 5 class: org.quartz.simpl.SimpleThreadPool
|
注意:同一集群下,instanceName必须相同,instanceId可自动生成,isClustered为true,持久化存储,指定数据库类型对应的驱动类和数据源连接。
- 自定义properties和配置类
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 26 27
| org.quartz.scheduler.instanceName = hyhScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.jobStore.class=org.springframework.scheduling.quartz.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.useProperties = true
org.quartz.jobStore.isClustered = true
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
|
配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Component public class JobFactory extends AdaptableJobFactory {
@Resource private AutowireCapableBeanFactory capableBeanFactory;
@Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object jobInstance = super.createJobInstance(bundle); capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }
|
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
| @Configuration public class JobConfig {
@Resource private JobFactory jobFactory; @Resource private DataSource dataSource;
@Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setJobFactory(jobFactory); schedulerFactoryBean.setDataSource(dataSource); schedulerFactoryBean.setOverwriteExistingJobs(true); schedulerFactoryBean.setStartupDelay(1); schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties")); return schedulerFactoryBean; }
@Bean public Scheduler scheduler() { return schedulerFactoryBean().getScheduler(); } }
|
基本使用
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
| @Component public class JobInit implements ApplicationRunner {
private static final String ID = "SUMMERDAY";
@Autowired private Scheduler scheduler;
@Override public void run(ApplicationArguments args) throws Exception { JobDetail jobDetail = JobBuilder.newJob(SecondJob.class) .withIdentity(ID + " 02") .storeDurably() .build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"); Trigger trigger = TriggerBuilder.newTrigger() .forJob(jobDetail) .withIdentity(ID + " 02Trigger") .withSchedule(scheduleBuilder) .startNow() .build(); Set<Trigger> set = new HashSet<>(); set.add(trigger); scheduler.scheduleJob(jobDetail, set, true); } }
|