SSM整合Quartz

本文详细介绍了如何在Spring中整合Quartz实现定时任务,包括在MySQL中创建Quartz所需表,添加相关依赖,配置quartz.properties,编写quartzConfig文件,以及静态和动态方式编写定时任务。此外,还解释了Quartz的核心要素,如Job、Trigger和Scheduler,以及cron表达式的使用。
摘要由CSDN通过智能技术生成

整合步骤:
1.在数据库中添加quartz的表
2.pom.xml文件中添加依赖
3.添加quartz.properties的配置
4.编写quartzConfig文件
5.编写定时任务

1.整合

1.1 mysql中创建quartz表

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set 
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#

DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;


CREATE TABLE QRTZ_JOB_DETAILS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    JOB_NAME  VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    JOB_CLASS_NAME   VARCHAR(250) NOT NULL,
    IS_DURABLE VARCHAR(1) NOT NULL,
    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);

CREATE TABLE QRTZ_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    JOB_NAME  VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    NEXT_FIRE_TIME BIGINT(13) NULL,
    PREV_FIRE_TIME BIGINT(13) NULL,
    PRIORITY INTEGER NULL,
    TRIGGER_STATE VARCHAR(16) NOT NULL,
    TRIGGER_TYPE VARCHAR(8) NOT NULL,
    START_TIME BIGINT(13) NOT NULL,
    END_TIME BIGINT(13) NULL,
    CALENDAR_NAME VARCHAR(200) NULL,
    MISFIRE_INSTR SMALLINT(2) NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
        REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);

CREATE TABLE QRTZ_SIMPLE_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    REPEAT_COUNT BIGINT(7) NOT NULL,
    REPEAT_INTERVAL BIGINT(12) NOT NULL,
    TIMES_TRIGGERED BIGINT(10) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_CRON_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    CRON_EXPRESSION VARCHAR(200) NOT NULL,
    TIME_ZONE_ID VARCHAR(80),
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  (          
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    STR_PROP_1 VARCHAR(512) NULL,
    STR_PROP_2 VARCHAR(512) NULL,
    STR_PROP_3 VARCHAR(512) NULL,
    INT_PROP_1 INT NULL,
    INT_PROP_2 INT NULL,
    LONG_PROP_1 BIGINT NULL,
    LONG_PROP_2 BIGINT NULL,
    DEC_PROP_1 NUMERIC(13,4) NULL,
    DEC_PROP_2 NUMERIC(13,4) NULL,
    BOOL_PROP_1 VARCHAR(1) NULL,
    BOOL_PROP_2 VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_BLOB_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    BLOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_CALENDARS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    CALENDAR_NAME  VARCHAR(200) NOT NULL,
    CALENDAR BLOB NOT NULL,
    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);

CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_GROUP  VARCHAR(200) NOT NULL, 
    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_FIRED_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    ENTRY_ID VARCHAR(95) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    FIRED_TIME BIGINT(13) NOT NULL,
    SCHED_TIME BIGINT(13) NOT NULL,
    PRIORITY INTEGER NOT NULL,
    STATE VARCHAR(16) NOT NULL,
    JOB_NAME VARCHAR(200) NULL,
    JOB_GROUP VARCHAR(200) NULL,
    IS_NONCONCURRENT VARCHAR(1) NULL,
    REQUESTS_RECOVERY VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);

CREATE TABLE QRTZ_SCHEDULER_STATE
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);

CREATE TABLE QRTZ_LOCKS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    LOCK_NAME  VARCHAR(40) NOT NULL, 
    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);


commit;

1.2 添加quartz依赖

        <!--quartz-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.3</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.3</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

1.3 添加quartz.properties与数据库关联

org.quartz.scheduler.instanceName=quartzScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.scheduler.wrapJobExecutionInUserTransaction=false
org.quartz.jobStore.misfireThreshold=50000
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.isClustered=true
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.clusterCheckinInterval=20000
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

数据库关联

package com.foxconn.fii.taskz.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

/**
 * @author
 */
@Configuration
@PropertySource("classpath:application.properties")
public class DataSourceQuartzConfig {

    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String user;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driverClassName}")
    private String driverClass;

    @Value("${spring.datasource.druid.maxActive}")
    private Integer maxActive;
    @Value("${spring.datasource.druid.minIdle}")
    private Integer minIdle;
    @Value("${spring.datasource.druid.initialSize}")
    private Integer initialSize;
    @Value("${spring.datasource.druid.maxWait}")
    private Long maxWait;
    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
    private Long timeBetweenEvictionRunsMillis;
    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
    private Long minEvictableIdleTimeMillis;
    @Value("${spring.datasource.druid.testWhileIdle}")
    private Boolean testWhileIdle;
    @Value("${spring.datasource.druid.testWhileIdle}")
    private Boolean testOnBorrow;
    @Value("${spring.datasource.druid.testOnBorrow}")
    private Boolean testOnReturn;

    @Bean(name = "quartzDataSource")
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);

        //连接池配置
        dataSource.setMaxActive(maxActive);
        dataSource.setMinIdle(minIdle);
        dataSource.setInitialSize(initialSize);
        dataSource.setMaxWait(maxWait);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestOnReturn(testOnReturn);
        dataSource.setValidationQuery("SELECT 'x'");

        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);

        return dataSource;
    }
}

1.4 编写quartzConfig文件

1.4.1 quartz的初始化配置
package com.fii.gac.web.config;

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

import javax.sql.DataSource;

import lombok.RequiredArgsConstructor;
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;

/**
 * quartz的初始化配置
 * @author Administrator
 *
 */
@Configuration
@RequiredArgsConstructor
public class QuartzConfiguration {
	
	private final QuartzJobFactory quartzJobFactory;

	private final DataSource dataSource;

    @Bean(name = "schedulerFactoryBean")
	public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        //获取配置属性
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        //在quartz.properties中的属性被读取并注入后再初始化对象
        propertiesFactoryBean.afterPropertiesSet();
        //创建SchedulerFactoryBean
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        Properties pro = propertiesFactoryBean.getObject();
        //覆盖已存在的任务
        factory.setOverwriteExistingJobs(true);
        // 设置自动启动
        factory.setAutoStartup(true);
        // 设置延迟10s启动
        factory.setStartupDelay(10);
        if (pro != null) {
            factory.setQuartzProperties(pro);
        }
        factory.setJobFactory(quartzJobFactory);
        factory.setDataSource(dataSource);
        return factory;
    }
}

1.4.2 创建job 实例工厂
package com.fii.gac.web.config;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.stereotype.Component;

/**
 * 创建job 实例工厂,解决spring注入问题,如果使用默认会导致spring的@Autowired 无法注入问题(很重要)
 * @author Administrator
 *
 */
@Component
public class QuartzJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

	private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        return job;
    }
	
}

1.5 编写定时任务

1.5.1 静态方式编写定时任务
 /**
     * 静态方式配置定时任务
     *
     * @param jobDetail
     * @return
     */
    @Bean
    public CronTriggerFactoryBean simpleJobTrigger(
            @Qualifier("simpleJobDetail") JobDetail jobDetail) {
        CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();

        factoryBean.setJobDetail(jobDetail);
        factoryBean.setStartDelay(1000L);
        factoryBean.setName("trigger2");
        factoryBean.setGroup("group1");
        //周1至周5,每天上午8点至下午18点,每分钟执行一次
        factoryBean.setCronExpression("0 0/1 8-18 ? * 2-6");

        return factoryBean;
    }

    @Bean
    public JobDetailFactoryBean simpleJobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();

        factoryBean.setJobClass(ScheduledJob.class);
        factoryBean.setGroup("group1");
        factoryBean.setName("job4");

        return factoryBean;
    }

执行结果:
执行结果

1.5.2 动态方式编写定时任务

代码不全,只是为了展示编写方法

public void execute(JobExecutionContext context) throws JobExecutionException {
        preExecute(context);
        try {
            executeWrapper(context);
            setStatus(1);
        } catch (Exception e) {
            setStatus(0);
            String exceptionString = Exceptions.getStackTrace(e);
            addDescription(exceptionString);
            log.error(exceptionString);

        }
        postExecute(context);
        clearAll();
    }

    protected void preExecute(JobExecutionContext context) {
        initThreadLocal();
        try {
            LocalDateTime now = LocalDateTime.now();
            JobKey jobKey = context.getJobDetail().getKey();
            JobDataMap jobDataMap = context.getMergedJobDataMap();
            String jobName = jobKey.getName();
            String jobGroup = jobKey.getGroup();

            // 更状态
            QuartzJobDetailPO jobDetailPO = quartzJobDetailMapper.findByGroupAndName(jobGroup, jobName);
            jobDetailPO.setStatus(1);
            quartzJobDetailMapper.updateById(jobDetailPO);

            jobDataMap.put("startTime", now);
            log.info("jobGroup: {}, jobName: {}, startTime: {}", jobGroup, jobName, DateTimes.dateTimeToString(now));
        } catch (Exception e) {
            log.error(Exceptions.getStackTrace(e));
        }
    }

    protected void postExecute(JobExecutionContext context) {
        try {
            LocalDateTime now = LocalDateTime.now();
            JobKey jobKey = context.getJobDetail().getKey();
            JobDataMap jobDataMap = context.getMergedJobDataMap();
            String jobName = jobKey.getName();
            String jobGroup = jobKey.getGroup();
            LocalDateTime startTime = (LocalDateTime) jobDataMap.get("startTime");
            int executeTime = (int) startTime.until(now, ChronoUnit.SECONDS);

            LoadDataJobResult result = LOAD_DATA_JOB_RESULT_THREAD_LOCAL.get();

            // 更新状态
            QuartzJobDetailPO jobDetailPO = quartzJobDetailMapper.findByGroupAndName(jobGroup, jobName);
            jobDetailPO.setLastRunResult(result.getStatus());
            jobDetailPO.setLastRunTime(startTime);
            jobDetailPO.setNextRunTime(Quartzs.getCronNextRunTime(jobDetailPO.getCronExpression()));
            jobDetailPO.setStatus(2);
            quartzJobDetailMapper.updateById(jobDetailPO);

            quartzJobLogMapper.insert(QuartzJobLogPO.builder()
                    .jobGroup(jobGroup)
                    .jobName(jobName)
                    .status(result.getStatus())
                    .description(result.getStatus() == 1 ? Jsons.objectToJson(result) : result.getDescription())
                    .executeTime(executeTime)
                    .addTime(now)
                    .build());

            log.info("jobGroup: {}, jobName: {}, endTime: {}, 耗时: {}", jobGroup, jobName,
                    DateTimes.dateTimeToString(now),
                    executeTime);
        }catch (Exception e) {
            log.error(Exceptions.getStackTrace(e));
        }
    }

2.quartz

2.1 quartz概念

Quartz是一个开源的任务调度框架。基于定时、定期的策略来执行任务是它的核心功能,可以用来创建简单或运行十个,百个,甚至是好几万个Jobs这样复杂的程序。quartz官网

2.2 quartz核心要素

Quartz有3个核心要素:调度器(Scheduler)、任务(Job)、触发器(Trigger)。

2.2.1 要素关系

quartz体系结构

2.2.2 要素作用
Job(任务):是一个接口,有一个方法void execute(),可以通过实现该接口来定义需要执行的任务(具体的逻辑代码)。

Trigger(触发器):描述触发Job执行的时间触发规则实现类SimpleTrigger和CronTrigger可以通过crom表达式定义出各种复杂的调度方案。

Scheduler(调度器):代表一个Quartz的独立运行容器。Trigger和JobDetail可以注册到Scheduler中。Scheduler可以将Trigger绑定到某一JobDetail上,这样当Trigger被触发时,对应的Job就会执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job.

补充说明

JobDetail:Quartz每次执行job时,都重新创建一个Job实例,会接收一个Job实现类,以便运行的时候通过newInstance()的反射调用机制去实例化Job.JobDetail是用来描述Job实现类以及相关静态信息,比如任务在scheduler中的组名等信息。

Calendar:是一些日历特定时间的集合。一个Trigger可以和多个 calendar关联,比如每周一早上10:00执行任务,法定假日不执行,则可以通过calendar进行定点排除。

2.3 quartz优点

Quartz提供了极为广泛的特性如持久化任务,集群和分布式任务等,其特点如下:

完全由Java写成,方便集成(Spring)
伸缩性
负载均衡
高可用性

2.4 quartz数据表

2.4.1 数据表获取路径

quartz数据表的获取路径: 官网—>官网下载quartz---->quartz-2.2.3-distribution.tar\quartz-2.2.3\docs\dbTables

多种数据表文件
数据库文件

2.4.1 数据表的作用
QRTZ_CALENDARS 以 Blob 类型存储 Quartz 的 Calendar 信息 

QRTZ_CRON_TRIGGERS 存储 Cron Trigger,包括 Cron表达式和时区信息 

QRTZ_FIRED_TRIGGERS 存储与已触发的 Trigger 相关的状态信息,以及相联 Job的执行信息 QRTZ_PAUSED_TRIGGER_GRPS 存储已暂停的 Trigger 组的信息 

QRTZ_SCHEDULER_STATE 存储少许的有关 Scheduler 的状态信息,和别的 Scheduler实例(假如是用于一个集群中) 对象

QRTZ_LOCKS 存储程序的悲观锁的信息(假如使用了悲观锁) 

QRTZ_JOB_DETAILS 存储每个已配置的 Job 的详细信息 

QRTZ_JOB_LISTENERS 存储有关已配置的 JobListener 的信息 

QRTZ_SIMPLE_TRIGGERS 存储简单的Trigger,包括重复次数,间隔,以及已触的次数 

QRTZ_BLOG_TRIGGERS Trigger 做为 Blob 类型存储(用于 Quartz 用户用 JDBC建立他们本身定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) 集群

QRTZ_TRIGGER_LISTENERS 存储已配置的 TriggerListener 的信息 配置

QRTZ_TRIGGERS 存储已配置的 Trigger 的信息 

2.5 cron表达式

cron表达式支持到七个,其中参数如下:
在这里插入图片描述
字符表达的意思

1)* 星号
使用星号(*) 指示着你想在这个域上包含所有合法的值,在你希望 trigger 在该域的所有有效值上被激发时使用 * 字符。例如,在月份域上使用星号意味着每个月都会触发这个 trigger。

  表达式样例:0 * 17 * * ? 
意义:每天从下午5点到下午5:59中的每分钟激发一次 trigger。它停在下午 5:59 是因为值 17 在小时域上,在下午 6 点时,小时变为 18 了,也就不再理会这个 trigger,直到下一天的下午5点。 


2)? 问号 

? 号只能用在日和周域上,但是不能在这两个域上同时使用。你可以认为 ? 字符是 "我并不关心在该域上是什么值。" 这不同于星号,星号是指示着该域上的每一个值。? 是说不为该域指定值。你为这两域的其中一个指定了值,那就必须在另一个字值上放一个 ?。
不能同时这两个域上指定值的理由是难以解释甚至是难以理解的。基本上,假定同时指定值的话,意义就会变得含混不清了:考虑一下,如果一个表达式在日域上有值11,同时在周域上指定了 WED。那么是要 trigger 仅在每个月的11号,且正好又是星期三那天被激发?还是在每个星期三的11号被激发呢?要去除这种不明确性的办法就是不能同时在这两个域上指定值。 

    表达式样例:0 10,44 14 ? 3 WEB 
意义:在三月中的每个星期三的下午 2:10 和 下午 2:44 被触发。

3), 逗号 
逗号 (,) 是用来在给某个域上指定一个值列表的。例如,使用值 0,15,30,45 在秒域上意味着每15秒触发一个 trigger。

表达式样例: 0 0,15,30,45 * * * ? 
意义:每刻钟触发一次 trigger。

4)/ 斜杠 

斜杠 (/) 是用于时间表的递增的。我们刚刚用了逗号来表示每15分钟的递增,但是我们也能写成这样 0/15。 

表达式样例: 0/15 0/30 * * * ? 
意义:在整点和半点时每15秒触发 trigger。

5)- 中划线 

中划线 (-) 用于指定一个范围。例如,在小时域上的 3-8 意味着 "3,4,5,6,7 和 8 点。"  域的值不允许回卷,所以像 50-10 这样的值是不允许的。 

表达式样例:0 45 3-8 ? * * 
意义:在上午的3点至上午的8点的45分时触发 trigger。

6)L 字母
L 说明了某域上允许的最后一个值。它仅被日和周域支持。当用在日域上,表示的是在月域上指定的月份的最后一天。例如,当月域上指定了 JAN 时,在日域上的 L 会促使 trigger 在1月31号被触发。假如月域上是 SEP,那么 L 会预示着在9月30号触发。换句话说,就是不管指定了哪个月,都是在相应月份的时最后一天触发 trigger。

表达式 0 0 8 L * ? 
意义是在每个月最后一天的上午 8:00 触发 trigger。在月域上的 * 说明是 "每个月"。 

当 L 字母用于周域上,指示着周的最后一天,就是星期六 (或者数字7)。所以如果你需要在每个月的最后一个星期六下午的 11:59 触发 trigger,你可以用这样的表达式 0 59 23 ? * L。 
当使用于周域上,你可以用一个数字与 L 连起来表示月份的最后一个星期 X。例如,表达式 0 0 12 ? * 2L 说的是在每个月的最后一个星期一触发 trigger。
不要让范围和列表值与 L 连用。虽然你能用星期数(1-7)与 L 连用,但是不允许你用一个范围值和列表值与 L 连用。这会产生不可预知的结果。

7)W 字母 
W 字符代表着*日 (Mon-Fri),并且仅能用于日域中。它用来指定离指定日的最*的一个*日。大部分的商业处理都是基于工作周的,所以 W 字符可能是非常重要的。例如,日域中的 15W 意味着 "离该月15号的最*一个*日。" 假如15号是星期六,那么 trigger 会在14号(星期四)触发,因为距15号最*的是星期一,这个例子中也会是17号(译者Unmi注:不会在17号触发的,如果是15W,可能会是在14号(15号是星期六)或者15号(15号是星期天)触发,也就是只能出现在邻*的一天,如果15号当天为*日直接就会当日执行)。W 只能用在指定的日域为单天,不能是范围或列表值。 

8)井号

井号字符仅能用于周域中。它用于指定月份中的第几周的哪一天。例如,如果你指定周域的值为 6#3,它意思是某月的第三个周五 (6=星期五,#3意味着月份中的第三周)。另一个例子 2#1 意思是某月的第一个星期一 (2=星期一,#1意味着月份中的第一周)。注意,假如你指定 #5,然而月份中没有第 5 周,那么该月不会触发。

例子:

表达式意义

"0 0 12 * *?" 每天中午12点触发

"0 15 10 ? **" 每天上午10:15触发

"0 15 10 * *?" 每天上午10:15触发

"0 15 10 * * ?*" 每天上午10:15触发

"0 15 10 * * ?2005" 2005年的每天上午10:15触发

"0 * 14 * *?" 在每天下午2点到下午2:59期间的每1分钟触发

"0 0/5 14 * *?" 在每天下午2点到下午2:55期间的每5分钟触发

"0 0/5 14,18 ** ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

"0 0-5 14 * *?" 在每天下午2点到下午2:05期间的每1分钟触发

"0 10,44 14 ? 3WED" 每年三月的星期三的下午2:10和2:44触发

"0 15 10 ? *MON-FRI" 周一至周五的上午10:15触发

"0 15 10 15 *?" 每月15日上午10:15触发

"0 15 10 L *?" 每月最后一日的上午10:15触发

"0 15 10 ? *6L" 每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6L2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发

"0 15 10 ? *6#3" 每月的第三个星期五上午10:15触发

3.参考文章

https://blog.csdn.net/chenmingxu438521/article/details/94485695
https://www.cnblogs.com/zhaobingqing/p/7449474.html
http://www.javashuo.com/article/p-dxpgfazn-bt.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值