HelloQuartz

3 篇文章 0 订阅

Quartz第一天内容

Quartz官方网站:http://www.quartz-scheduler.org

什么是Quartz?

- Quartz是一个功能非常强大的开源的作业调度框架;
- 几乎可以集成任何java应用,小到单体应用,达到大型电子商务系统;
- 可以用来执行成千上万的简单或者复杂的调度任务;
- Quartz的任务被定义为一组标准的java组件,几乎可以执行任何编程任务;
- Quartz包含了一些企业级功能:包括对JTA事务支持和集群功能;

Quartz能做什么?

定时发送邮件、短信通知;
数据同步; 

Quartz特点

强大的调度功能;
灵活的使用方式;
表达式 秒  分  时  天  月  周
       0  0  8   ?   5  SUN#3

集群功能;

Quartz的重要API

Job接口:任务;定义的任务要实现Job接口;
JobDetail:对任务的描述;
Trigger:触发器,可以定义任务执行时机、执行规则
 - SimpleTrigger
 - CronTrigger
Scheduler:任务容器,调度器,使用触发器定义的规则去调度任务;
JobStore:内存、JDBC;

第一个Quartz程序:每隔5秒钟打印一次Hello Quartz!

引入Quartz依赖
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>

首先编写任务:HelloQuartz implements Job
HelloQuartzMain 
  - 创建JobDetail
  - 创建Trigger
  - 创建Scheduler
  - 启动调度

在这里插入图片描述

package com.etoak.quartz01;

import org.quartz.Job;
import org.quartz.JobExecutionContext;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class HelloQuartzJob implements Job {

    public HelloQuartzJob() {
        System.out.println("创建HelloQuartzJob对象");
    }

    @Override
    public void execute(JobExecutionContext context) {
        LocalDateTime dateTime = LocalDateTime.now();
        String date = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS"));
        System.out.println(date + "-Hello Quartz!");
    }
}

package com.etoak.quartz01;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class HelloQuartzMain {

    public static void main(String[] args) throws SchedulerException {
        // 1.创建JobDetail,使用建造者模式
        JobDetail jobDetail = JobBuilder.newJob(HelloQuartzJob.class)
                .withIdentity("hello", "hello")
                .build();

        // 2.创建Trigger
        SimpleTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("hello", "hello")
                .withSchedule(SimpleScheduleBuilder
                        .simpleSchedule()
                        .withIntervalInSeconds(5) // 每5秒钟执行一次
                        .repeatForever()
                ).build();

        // 3.创建Scheduler
        Scheduler scheduler = StdSchedulerFactory
                .getDefaultScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }
}

在这里插入图片描述

JobDetail和Trigger如何给Job任务传参、讲解SimpleTrigger

1. 任务两秒后执行、之后每隔三秒执行一次;
JobDetail给Job任务传参
usingJobData(); 
package com.etoak.quartz02;

import org.quartz.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class JobDetailParamJob implements Job {

    private Integer id;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail jobDetail = context.getJobDetail();
        JobDataMap dataMap = jobDetail.getJobDataMap();
        String first = dataMap.getString("first");

        String date = LocalDateTime.now()
                .format(DateTimeFormatter
                        .ofPattern("yyyy-MM-dd HH:mm:ss"));

        System.out.println(date + "-first:" + first);
        System.out.println(date + "-second:" + id);

        boolean third = dataMap.getBoolean("third");
        System.out.println(date + "-third:" + third);

    }
}

package com.etoak.quartz02;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;

// 任务两秒后执行、之后每隔三秒执行一次;
// JobDetail给Job任务传参
public class JobDetailParamMain {
    public static void main(String[] args) throws SchedulerException {

        JobDataMap dataMap = new JobDataMap();
        dataMap.put("third", true);

        JobDetail jobDetail = JobBuilder.newJob(JobDetailParamJob.class)
            .withIdentity("param")
            .usingJobData("first", "第一种传参")
            .usingJobData("id", 100)
            .usingJobData(dataMap)
            .build();

        // 创建Trigger
        Date current = new Date();
        System.out.println( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(current));

        // 获得两秒后时间
        Date twoSecondsAfter = new Date(current.getTime() + 2000L);
        SimpleTrigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("param")
            .startAt(twoSecondsAfter) //两秒后开始执行
            .withSchedule(SimpleScheduleBuilder
                    .simpleSchedule()
                    .withIntervalInSeconds(3) //之后每隔3秒执行一次
                    .repeatForever()
            ).build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }
}

在这里插入图片描述

2. 任务两秒后执行,之后每隔三秒一次,15秒后停止执行;
Trigger给Job任务传参
usingJobData()
package com.etoak.quartz03;

import org.quartz.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TriggerParamJob implements Job {

    private Integer second;

    public Integer getSecond() {
        return second;
    }

    public void setSecond(Integer second) {
        this.second = second;
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Trigger trigger = context.getTrigger();
        JobDataMap dataMap = trigger.getJobDataMap();
        String first = dataMap.getString("first");
        boolean third = dataMap.getBoolean("third");

        String date = LocalDateTime.now()
                .format(DateTimeFormatter
                        .ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println(date + "-first:" + first);
        System.out.println(date + "-second:" + second);

        System.out.println(date + "-third:" + third);
    }
}

这里时间用的是LocalDateTime,传参的时候转了格式
Java 8时间接口localDateTime和Date的对比

package com.etoak.quartz03;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class TriggerParamJobMain {
    public static void main(String[] args) throws SchedulerException {

        JobDetail jobDetail = JobBuilder.newJob(TriggerParamJob.class)
                .withIdentity("param", "param")
                .build();

        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前时间:" + now);
        LocalDateTime twoSecondsAfter = now.plusSeconds(2);
        LocalDateTime fifteenSecondsAfter = now.plusSeconds(15);
        Date two = Date.from(twoSecondsAfter.atZone(ZoneId.systemDefault()).toInstant());
        Date fifteen = Date.from(fifteenSecondsAfter.atZone(ZoneId.systemDefault()).toInstant());

        JobDataMap dataMap = new JobDataMap();
        dataMap.put("third", false);

        SimpleTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("param")
                .startAt(two)
                .endAt(fifteen)
                .usingJobData("first", "第一种方式")
                .usingJobData("second", 2)
                .usingJobData(dataMap)
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(3)
                        .repeatForever()
                ).build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();

    }

}

在这里插入图片描述

3. 任务两秒后执行,之后每隔三秒执行一次,执行2次;
合并JobDetail和Trigger的参数
package com.etoak.quartz04;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

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

public class MergeParamJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap dataMap = context.getMergedJobDataMap();
        String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Set<Map.Entry<String, Object>> entrySet = dataMap.entrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(date + "-" + key + ':' + value);
        }

    }
}

package com.etoak.quartz04;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MegerParamMain {
    public static void main(String[] args) throws SchedulerException {

        Date current = new Date();
        System.out.println( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(current));

        // 获得两秒后时间
        Date twoSecondsAfter = new Date(current.getTime() + 2000L);
        SimpleTrigger trigger = TriggerBuilder.newTrigger()
                .usingJobData("third", 3)
                .usingJobData("second", "trigger")
                .startAt(twoSecondsAfter)
                .withSchedule(SimpleScheduleBuilder
                        .simpleSchedule().withIntervalInSeconds(3)
                        .withRepeatCount(2)
                ).build();

        JobDetail jobDetail = JobBuilder.newJob(MergeParamJob.class)
                .usingJobData("first", "first")
                .usingJobData("second", "JobDetail")
                .build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }
}

上面的两次指的是第一次执行之后再执行两次。

Cron表达式

Cron-Expressions用于配置CronTrigger的实例。
Cron Expressions是由七个子表达式组成的字符串,用于描述时间的各个细节。这些子表达式用空格分隔,并表示:
[秒]     [分]     [小时]   [天]         [月]    [周]        [年]
Seconds  Minutes  Hours  Day-of-Month  Month  Day-of-Week  Year (optional field)

时间字段	  是否必填	允许值	         特殊字符
 秒	        是	     0-59             ,-*/ 
 分	        是	     0-59             ,-*/
 时	        是	     0-23             ,-*/
 日	        是	     1-31             , - * ? / L W C
 月	        是    1-12或者JAN-DEC     ,-*/
 周	        是    1-7或者SUN-SAT      ,-* ? / L C #      说明:周天用1表示,依次类推
 年	        否    空或1970-2099        ,-*/
 ,:表示或的关系
 -:范围的关系【比如1-21】
 *:每秒、每分、每小时等 
 /:每天哪个时间执行
 L:用于每月,或每周,表示为每月的最后一天,或每个月的最后星期几如“6L”表示“每月的最后一个星期五”
 W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。
  例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;
  如果15号是星期二,那结果就是15号星期二。
  但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。
 W字符串只能指定单一日期,而不能指定日期范围;
 #:是用来指定“的”每月第n个工作日,例在每周(day-of-week)这个字段中内容为"6#3" or "FRI#3" 则表示“每月第三个星期五”

 表达式举例
   每天14:20提醒打卡:0 20 14 ? * MON-FRI
   每天1点到1点59分,每隔5分执行:0 0/5 1 * * ?
   周一到周五9:00上班的时候执行:0 0 9 ? * 2-6

 注意点:?只能用在"天和周"
        如果有一个字段是*,那么另外一个用?;
        天和周有一个确定了,另外一个就得用?;
package com.etoak.quartz05;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;

public class CronJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println(
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                .format(new Date()) + "-Hello Quartz"
        );
    }
}

package com.etoak.quartz05;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class CronJobMain {

    public static void main(String[] args) throws SchedulerException {
        // JobDetail
        JobDetail jobDetail = JobBuilder.newJob(CronJob.class)
                .withIdentity("cron", "cron")
                .build();

        // Trigger
        CronTrigger trigger = TriggerBuilder
                .newTrigger()
                .withSchedule(CronScheduleBuilder
                        .cronSchedule("0/5 * * * * ?")
                ).build();

        // Scheduler
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }
}

整合Spring

maven依赖
org.quartz-scheduler:quartz:2.3.0
org.springframework:spring-jdbc:5.0.7.RELEASE
org.springframework:spring-tx:5.0.7.RELEASE
org.springframework:spring-context-support:5.0.7.RELEASE
配置ioc容器中的bean
MethodInvokingJobDetailFactoryBean
  特点:不要求任务类实现任何接口
  属性:name、group、targetObject(job bean)、targetMethod(方法名)
CronTriggerFactoryBean
  属性:name、group、jobDetail、cronExpression
SchedulerFactoryBean
  属性:triggers --> list
<!-- MethodInvokingJobDetailFactory
     不要求任务类实现Job接口
 -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
	<property name="name" value="springJob" />
	<property name="group" value="springJob" />
	<property name="targetObject" ref="springJob" />
	<property name="targetMethod" value="executeJob" />
</bean>
<!-- 任务类 -->
<bean id="springJob" class="com.etoak.job.SpringJob" />

<!-- CronTriggerFactoryBean -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	<property name="group" value="springJob" />
	<property name="name" value="springJob" />
	<property name="jobDetail" ref="jobDetail" />
	<property name="cronExpression" value="0/5 * * ? * *" />
</bean>

<!-- SchedulerFactoryBean -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
			<ref bean="cronTrigger" />
		</list>
	</property>
</bean>

Quartz集群

1. 创建数据库和表
创建一个名称为quartz的数据库(字符集编码:utf8)
创建表:执行tables_mysql_innodb.sql
2. 创建项目,添加maven依赖
org.quartz-scheduler:quartz:2.3.0
org.springframework:spring-jdbc:5.0.7.RELEASE
org.springframework:spring-tx:5.0.7.RELEASE
org.springframework:spring-context-support:5.0.7.RELEASE
mysql:mysql-connector-java:5.1.34
3. 将quartz.properties文件放在src/main/resources下
在配置SchedulerFactoryBean的时候,有个configLocation属性,指定quartz.properties文件的位置;

#可以设置为任意,用在 JDBC JobStore中来唯一标识实例,但是所有集群节点中必须相同。
org.quartz.scheduler.instanceName=SpringClusterTest
# 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID 
org.quartz.scheduler.instanceId = AUTO 

## 线程
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

## 存储
org.quartz.jobStore.misfireThreshold = 60000
#JobStoreTX,将任务持久化到数据库中。因为集群中节点依赖于数据库来传播 Scheduler实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储,不能在集群中使用 RAMJobStore。
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
#值 true,表示 Scheduler实例要参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。
org.quartz.jobStore.isClustered = true 
#定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。
org.quartz.jobStore.clusterCheckinInterval = 5000
4. 配置spring容器
DataSource(HikariDataDource)
  属性:driverClassName、jdbcUrl、username、password
DataSourceTransactionManager
  属性:dataSource

JobDetailFactoryBean
  属性:name、group、jobClass、durability(持久化任务)
  特点:要求任务继承QuartzJobBean类

CronTriggerFactoryBean
  属性:name、group、jobDetail、cronExpression

SchedulerFactoryBean
  属性:triggers、configLocation、dataSource、transactionManager、applicationContextSchedulerContextKey(spring ioc)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值