Quartz
整合步骤:
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 要素关系
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