使用quartz和Spring-Task实现计划任务的四种方式
2017-06-27 16:38
666 查看
范培忠 2017-06-27
在我们日常开发中,有一些应用场景有实现计划任务的需要,如在夜晚启动对账处理,当日数据推历史及次日初始化,定时放出某可用资源等操作。
使用quartz和Spring-Task都可在Java后端实现此计划任务功能,而每种方式又可细分成两种小的方式,本文进行简明的介绍。其中方式一、二基于quartz,区别是使用JobDetailFactoryBean或MethodInvokingJobDetailFactoryBean,后者是由Spring提供支持,不需要集成quartz的抽象类要更灵活一些;Spring从3之后就提供了Spring-Task模块直接实现了计划任务支持,但它属于轻量化的。方式三、四使用Spring-Task实现,区别是使用xml或注解配置。四种方式均亲测有源码。
方式一:继承quartz的JobDetailFactoryBean类
一、项目结构
二、编写具体的任务内容类
三、Spring配置文件
(一)定义任务内容
(二)定义CornTrigger触发器
(三)配置核心调度器
四、执行效果
方式二 基于Spring的MethodInvokingJobDetailFactoryBean
此种方式,不用继承quartz类,但在pom里仍然要依赖quartz,否则配置调度工厂时不能识别。
一、项目结构
二、编写具体的任务内容类
三、Spring配置文件
(一)定义任务内容
(二)定义CornTrigger触发器
(三)配置调度工厂
四、执行效果
方式三:Spring-Task
Spring-Task是Spring3.0以后自主开发的定时任务工具,spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种。注解比较方便,代码量少,但是他人运维时不容易找到配置的地方。
方式三-1:配置文件方式
一、项目结构
二、编写具体的任务内容类
三、Spring配置文件
四、执行效果
方式三-2:注解方式
一、项目结构
二、编写具体的任务内容类
三、Spring配置文件
四、执行效果
ps:配置
JobDetail
JobDetail 用来保存我们作业的详细信息。一个JobDetail可以有多个Trigger,但是一个Trigger只能对应一个JobDetail。下面是JobDetail的一些常用的属性和含义
如:
[java] view
plain copy
<bean id="myjob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.tgb.lk.demo.quartz.MyJob1" />
<property name="durability" value="true" />
</bean>
JobDataMap
这是一个给作业提供数据支持的数据结构,使用方法和Java.util.Map一样,非常方便。当一个作业被分配给调度器时,JobDataMap实例就随之生成。
Job有一个StatefulJob子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。无状态任务在执行时拥有自己的JobDataMap拷贝,对JobDataMap的更改不会影响下次的执行。而有状态任务共享共享同一个JobDataMap实例,每次任务执行对JobDataMap所做的更改会保存下来,后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行发生影响。
正因为这个原因,无状态的Job可以并发执行,而有状态的StatefulJob不能并发执行,这意味着如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量使用无状态的Job。
如果Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在Scheduler注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。
JobDataMap实例也可以与一个触发器相关联。这种情况下,对于同一作业的不同触发器,我们可以在JobDataMap中添加不同的数据,以便作业在不同时间执行时能够提供更为灵活的数据支持(学校上午放眼保健操录音第一版,下午放第二版)。
不管是有状态还是无状态的任务,在任务执行期间对Trigger的JobDataMap所做的更改都不会进行持久,也即不会对下次的执行产生影响。
SimpleTrigger
这是一个简单的触发器,通过它我们可以定义触发的时间,并选择性的设定重复的次数和间隔时间。它有以下常用的属性
CronTrigger
这个触发器的功能非常强大,而且非常灵活,但需要掌握有关的Cron表达式知识
PS:corn表达式配置 corn配置
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
按顺序依次为:
秒(0~59)
分钟(0~59)
小时(0~23)
天(月)(0~31,但是你需要考虑你月的天数)
月(0~11)
天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
7.年份(1970-2099)
字段允许值
允许的特殊字符
========================================================
秒0-59
, - * /
分0-59
, - * /
小时0-23
, - * /
日期1-31
, - * ? / L W C
月份1-12 或者 JAN-DEC
, - * /
星期1-7 或者 SUN-SAT
, - * ? / L C #
年(可选)留空, 1970-2099
, - * /
其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
"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 ? 3 WED" 每年三月的星期三的下午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 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
“-”有些子表达式能包含一些范围或列表
例如:子表达式(天(星期))可以为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”
“*”字符代表所有可能的值
因此,“*”在子表达式(月)里表示每个月的含义,“*”在子表达式(天(星期))表示星期的每一天
“/”字符用来指定数值的增量
例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟
在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样
“?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值
当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”
“L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写。但是它在两个子表达式里的含义是不同的。
在天(月)子表达式中,“L”表示一个月的最后一天
在天(星期)自表达式中,“L”表示一个星期的最后一天,也就是SAT
如果在“L”前有具体的内容,它就具有其他的含义了
例如:“6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五
注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题。
在我们日常开发中,有一些应用场景有实现计划任务的需要,如在夜晚启动对账处理,当日数据推历史及次日初始化,定时放出某可用资源等操作。
使用quartz和Spring-Task都可在Java后端实现此计划任务功能,而每种方式又可细分成两种小的方式,本文进行简明的介绍。其中方式一、二基于quartz,区别是使用JobDetailFactoryBean或MethodInvokingJobDetailFactoryBean,后者是由Spring提供支持,不需要集成quartz的抽象类要更灵活一些;Spring从3之后就提供了Spring-Task模块直接实现了计划任务支持,但它属于轻量化的。方式三、四使用Spring-Task实现,区别是使用xml或注解配置。四种方式均亲测有源码。
方式一:继承quartz的JobDetailFactoryBean类
一、项目结构
二、编写具体的任务内容类
package util; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import java.time.LocalTime; public class TaskWork extendsQuartzJobBean { private int timeout; private static int i = 0; //调度工厂实例化后,经过timeout时间开始执行调度 public void setTimeout(int timeout) { this.timeout = timeout; } /* 要调度的具体任务*/ @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { LocalTime lt = LocalTime.now(); String sTime = lt.getHour() + ":" + lt.getMinute() + ":" + lt.getSecond(); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); System.out.println("定时任务执行中,[" + sTime + "]"); } }
三、Spring配置文件
(一)定义任务内容
<!--Spring 定时任务配置--> <bean name="job1" id="job1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <!-- durability 如果一个job是非持久的,当没有活跃的trigger与之关联的时候,会被自动地从scheduler中删除。 也就是说,非持久的job的生命期是由trigger的存在与否决定的;默认false --> <property name="durability" value="true"/> <property name="jobClass" value="util.TaskWork"/> <!-- jobDataAsMap没有用,此目标类中接受的参数 ,若参数为service,则可以在此进行参数配置,类似struts2 --> <!--<property name="jobDataAsMap"> <map> <entry key="timeout" value="0"/> </map> </property>--> </bean>
(二)定义CornTrigger触发器
<!-- 定义CornTrigger触发器 定时执行--> <bean id="cornTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="job1"/> <!-- 在每天13点46分触发,正则表示的配置可以使用 http://cron.qqe2.com/ --> <property name="cronExpression" value="0 46 13 * * ? "/> </bean>
<!-- 定义simpleTrigger触发器 间隔执行--> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="jobDetail"></property> <property name="repeatCount"> <value>8</value> </property> <property name="repeatInterval"> <value>1000</value> </property> <property name="startDelay"> <value>4</value> </property> </bean>
(三)配置核心调度器
<!--核心调度器--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cornTrigger"/> </list> </property> </bean>
四、执行效果
方式二 基于Spring的MethodInvokingJobDetailFactoryBean
此种方式,不用继承quartz类,但在pom里仍然要依赖quartz,否则配置调度工厂时不能识别。
一、项目结构
二、编写具体的任务内容类
package util; import org.quartz.JobExecutionException; import java.time.LocalTime; public class TaskWork { //要调度的具体任务,必须要设置成public public void execute() throws JobExecutionException { LocalTime lt = LocalTime.now(); String sTime = lt.getHour() + ":" + lt.getMinute() + ":" + lt.getSecond(); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); System.out.println("定时任务执行中2,[" + sTime + "]"); } }
三、Spring配置文件
(一)定义任务内容
<!--Spring 定时任务配置--> <bean id="job2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <bean class="util.TaskWork"/> </property> <property name="targetMethod"> <value>execute</value> </property> </bean>
(二)定义CornTrigger触发器
<!-- 定义CornTrigger触发器 定时执行--> <bean id="cornTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="job2"/> <property name="cronExpression" value="0 58 13 * * ? "/> </bean>
<!-- 定义simpleTrigger触发器 间隔执行--> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="jobDetail"></property> <property name="repeatCount"> <value>8</value> </property> <property name="repeatInterval"> <value>1000</value> </property> <property name="startDelay"> <value>4</value> </property> </bean>
(三)配置调度工厂
<!--配置调度工厂--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean 136d2 "> <property name="triggers"> <list> <ref bean="cornTrigger"/> </list> </property> </bean>
四、执行效果
方式三:Spring-Task
Spring-Task是Spring3.0以后自主开发的定时任务工具,spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种。注解比较方便,代码量少,但是他人运维时不容易找到配置的地方。
方式三-1:配置文件方式
一、项目结构
二、编写具体的任务内容类
package util; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component(value = "taskWork") public class TaskWork { //要调度的具体任务,必须要设置成public public void execute1() { System.out.printf("execute: %s, Current time: %s\n", 1, LocalDateTime.now()); } public void execute2() { System.out.printf("execute: %s, Current time: %s\n", 2, LocalDateTime.now()); } public void execute3() { System.out.printf("execute: %s, Current time: %s\n", 3, LocalDateTime.now()); } public void execute4() { System.out.printf("execute: %s, Current time: %s\n", 4, LocalDateTime.now()); } public void execute5() { System.out.printf("execute: %s, Current time: %s\n", 5, LocalDateTime.now()); } public void execute6() { System.out.printf("execute: %s, Current time: %s\n", 6, LocalDateTime.now()); } public void execute7() { System.out.printf("execute: %s, Current time: %s\n", 7, LocalDateTime.now()); } public void execute8() { System.out.printf("execute: %s, Current time: %s\n", 8, LocalDateTime.now()); } public void execute9() { System.out.printf("execute: %s, Current time: %s\n", 9, LocalDateTime.now()); } public void execute10() { System.out.printf("execute: %s, Current time: %s\n", 10, LocalDateTime.now()); } public void execute11() { System.out.printf("execute: %s, Current time: %s\n", 11, LocalDateTime.now()); } }
三、Spring配置文件
<!--扫描计划任务类--> <context:component-scan base-package="util"/> <!--定义计划任务资源池--> <task:scheduler id="taskScheduler" pool-size="100"/> <!--具体任务配置--> <task:scheduled-tasks scheduler="taskScheduler"> <!-- 每半分钟触发任务 --> <task:scheduled ref="taskWork" method="execute1" cron="30 * * * * ?"/> <!-- 每小时的10分30秒触发任务 --> <task:scheduled ref="taskWork" method="execute2" cron="30 10 * * * ?"/> <!-- 每天1点10分30秒触发任务 --> <task:scheduled ref="taskWork" method="execute3" cron="30 10 1 * * ?"/> <!-- 每月20号的1点10分30秒触发任务 --> <task:scheduled ref="taskWork" method="execute4" cron="30 10 1 20 * ?"/> <!-- 每年10月20号的1点10分30秒触发任务 --> <task:scheduled ref="taskWork" method="execute5" cron="30 10 1 20 10 ?"/> <!-- 每15秒、30秒、45秒时触发任务 --> <task:scheduled ref="taskWork" method="execute6" cron="15,30,45 * * * * ?"/> <!-- 15秒到45秒每隔1秒触发任务 --> <task:scheduled ref="taskWork" method="execute7" cron="15-45 * * * * ?"/> <!-- 每分钟的每15秒时任务任务,每隔5秒触发一次 --> <task:scheduled ref="taskWork" method="execute8" cron="15/5 * * * * ?"/> <!-- 每分钟的15到30秒之间开始触发,每隔5秒触发一次 --> <task:scheduled ref="taskWork" method="execute9" cron="15-30/5 * * * * ?"/> <!-- 每小时的0分0秒开始触发,每隔3分钟触发一次 --> <task:scheduled ref="taskWork" method="execute10" cron="0 0/3 * * * ?"/> <!-- 星期一到星期五的10点15分0秒触发任务 --> <task:scheduled ref="taskWork" method="execute11" cron="0 15 10 ? * MON-FRI"/> </task:scheduled-tasks>
四、执行效果
方式三-2:注解方式
一、项目结构
二、编写具体的任务内容类
package util; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component(value = "taskWork") public class TaskWork { //要调度的具体任务,必须要设置成public /*每半分钟触发任务*/ @Scheduled(cron = "30 * * * * ?") public void execute1() { System.out.printf("execute: %s, Current time: %s\n", 1, LocalDateTime.now()); } /*每小时的10分30秒触发任务*/ @Scheduled(cron = "30 10 * * * ?") public void execute2() { System.out.printf("execute: %s, Current time: %s\n", 2, LocalDateTime.now()); } /*每天1点10分30秒触发任务*/ @Scheduled(cron = "30 10 1 * * ?") public void execute3() { System.out.printf("execute: %s, Current time: %s\n", 3, LocalDateTime.now()); } /*每月20号的1点10分30秒触发任务*/ @Scheduled(cron = "30 10 1 20 * ?") public void execute4() { System.out.printf("execute: %s, Current time: %s\n", 4, LocalDateTime.now()); } /*每年10月20号的1点10分30秒触发任务*/ @Scheduled(cron = "30 10 1 20 10 ?") public void execute5() { System.out.printf("execute: %s, Current time: %s\n", 5, LocalDateTime.now()); } /*每15秒、30秒、45秒时触发任务*/ @Scheduled(cron = "15,30,45 * * * * ?") public void execute6() { System.out.printf("execute: %s, Current time: %s\n", 6, LocalDateTime.now()); } /*15秒到45秒每隔1秒触发任务*/ @Scheduled(cron = "15-45 * * * * ?") public void execute7() { System.out.printf("execute: %s, Current time: %s\n", 7, LocalDateTime.now()); } /*每分钟的每15秒时任务任务,每隔5秒触发一次*/ @Scheduled(cron = "15/5 * * * * ?") public void execute8() { System.out.printf("execute: %s, Current time: %s\n", 8, LocalDateTime.now()); } /*每分钟的15到30秒之间开始触发,每隔5秒触发一次*/ @Scheduled(cron = "15-30/5 * * * * ?") public void execute9() { System.out.printf("execute: %s, Current time: %s\n", 9, LocalDateTime.now()); } /*每小时的0分0秒开始触发,每隔3分钟触发一次*/ @Scheduled(cron = "0 0/3 * * * ?") public void execute10() { System.out.printf("execute: %s, Current time: %s\n", 10, LocalDateTime.now()); } /*星期一到星期五的10点15分0秒触发任务*/ @Scheduled(cron = "0 15 10 ? * MON-FRI") public void execute11() { System.out.printf("execute: %s, Current time: %s\n", 11, LocalDateTime.now()); } }
三、Spring配置文件
<!--扫描计划任务类--> <context:component-scan base-package="util"/> <!--定义计划任务资源池--> <task:scheduler id="taskScheduler" pool-size="100"/> <!--开启这个配置,spring才能识别@Scheduled注解 --> <task:annotation-driven scheduler="taskScheduler" mode="proxy"/>
四、执行效果
ps:配置
JobDetail
JobDetail 用来保存我们作业的详细信息。一个JobDetail可以有多个Trigger,但是一个Trigger只能对应一个JobDetail。下面是JobDetail的一些常用的属性和含义
参数名 | 类型 | 备注 |
name | String | 任务的名称,必须 |
group | String | 任务所在组,默认为DEFAULT |
jobClass | Class | 任务的实现类,必须 |
description | String | 描述 |
jobDataMap | JobDataMap | 用来给作业提供数据支持的数据结构 |
volatility | Boolean | 重启应用之后是否删除任务的相关信息,默认false |
durability | Boolean | 任务完成之后是否依然保留到数据库,默认false |
shouldRecover | Boolean | 应用重启之后时候忽略过期任务,默认false |
jobListeners | Set | 监听器 |
[java] view
plain copy
<bean id="myjob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.tgb.lk.demo.quartz.MyJob1" />
<property name="durability" value="true" />
</bean>
JobDataMap
这是一个给作业提供数据支持的数据结构,使用方法和Java.util.Map一样,非常方便。当一个作业被分配给调度器时,JobDataMap实例就随之生成。
Job有一个StatefulJob子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。无状态任务在执行时拥有自己的JobDataMap拷贝,对JobDataMap的更改不会影响下次的执行。而有状态任务共享共享同一个JobDataMap实例,每次任务执行对JobDataMap所做的更改会保存下来,后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行发生影响。
正因为这个原因,无状态的Job可以并发执行,而有状态的StatefulJob不能并发执行,这意味着如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量使用无状态的Job。
如果Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在Scheduler注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。
JobDataMap实例也可以与一个触发器相关联。这种情况下,对于同一作业的不同触发器,我们可以在JobDataMap中添加不同的数据,以便作业在不同时间执行时能够提供更为灵活的数据支持(学校上午放眼保健操录音第一版,下午放第二版)。
不管是有状态还是无状态的任务,在任务执行期间对Trigger的JobDataMap所做的更改都不会进行持久,也即不会对下次的执行产生影响。
SimpleTrigger
这是一个简单的触发器,通过它我们可以定义触发的时间,并选择性的设定重复的次数和间隔时间。它有以下常用的属性
参数名 | 参数类型 | 备注 |
name | String | 触发器名称 |
group | String | 触发器组名称 |
repeatCount | int | 重复次数,注意:如果为0表示不执行,-1表示不限制次数(直到过期),默认为0 |
repeatInterval | long | 间隔时间,注意:是以毫秒为单位 |
startTime | Date | 开始时间,默认当前时间 |
endTime | Date | 过期时间,默认一直执行(直到执行次数已达到repeatCount) |
这个触发器的功能非常强大,而且非常灵活,但需要掌握有关的Cron表达式知识
参数名 | 参数类型 | 备注 |
name | String | 触发器名称 |
group | String | 触发器组名称 |
cronEx | CronExpression | 规则表达式 |
startTime | Date | 开始时间,默认当前时间 |
endTime | Date | 过期时间,默认一直执行(直到执行次数已达到repeatCount) |
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
按顺序依次为:
秒(0~59)
分钟(0~59)
小时(0~23)
天(月)(0~31,但是你需要考虑你月的天数)
月(0~11)
天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
7.年份(1970-2099)
字段允许值
允许的特殊字符
========================================================
秒0-59
, - * /
分0-59
, - * /
小时0-23
, - * /
日期1-31
, - * ? / L W C
月份1-12 或者 JAN-DEC
, - * /
星期1-7 或者 SUN-SAT
, - * ? / L C #
年(可选)留空, 1970-2099
, - * /
其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
"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 ? 3 WED" 每年三月的星期三的下午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 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
“-”有些子表达式能包含一些范围或列表
例如:子表达式(天(星期))可以为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”
“*”字符代表所有可能的值
因此,“*”在子表达式(月)里表示每个月的含义,“*”在子表达式(天(星期))表示星期的每一天
“/”字符用来指定数值的增量
例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟
在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样
“?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值
当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”
“L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写。但是它在两个子表达式里的含义是不同的。
在天(月)子表达式中,“L”表示一个月的最后一天
在天(星期)自表达式中,“L”表示一个星期的最后一天,也就是SAT
如果在“L”前有具体的内容,它就具有其他的含义了
例如:“6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五
注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题。
相关文章推荐
- 使用Spring来实现任务计划服务二:不继承java.util.TimerTask
- 使用Spring来实现任务计划服务三:集成quartz任务调度框架
- 使用Spring来实现任务计划服务一:继承java.util.TimerTask
- 使用spring quartz实现任务调度(注解方式)
- spring使用Quartz实现定时任务
- Spring3.1.0+Quartz1.8.6整合实现计划任务
- 使用Spring的Quartz方式实现Java定时器功能
- Spring-task 使用注解(@Scheduled)创建计划任务
- 使用spring quartz实现定时任务
- java计划任务调度框架quartz结合spring实现调度的配置实例代码分享
- spring(基础五) spring实现后台的任务调度TimerTask和Quartz
- spring3中使用task实现计划任务
- Spring task quartz 定时任务的几种实现
- Spring整合的quartz任务调度的实现方式
- spring和quartz整合实现定时任务(配置文件配置方式
- Spring+Quartz实现计划任务
- Quartz实现的Web schedule (Spring计划任务)
- 使用System.Threading的Timer&Quartz.net两种方式实现定时执行任务,防止IIS释放timer对象
- Spring实现后台的任务调度TimerTask和Quartz
- Spring中使用quartz执行定时任务的两种方式