任务调度的时机(背景)
例如在开发购物网站时会遇到一个问题,因白天订单多流量大,为减轻网站压力要求一些不是太急的任务(如给注册用户发送广告邮件、清理日常垃圾信息等)放在凌晨流量较小时间段去执行,这个时候就需要使用到任务调度,指定在某个时间内执行某个任务
任务调度实现方式
- 借助java.util.Timer来实现的。对于更加复杂任务调度,Timer不太容易(定时器)
- 使用Spring的Quartz调度器可弥补Timer的不足,使开发者能完成各种复杂任务调度(调度器)
spring调度器(Quartz)
介绍
Quartz调度器为调度工作提供更丰富的支持,与Java定时器一样,可使用Quartz指定每隔多少毫秒执行一个工作,但Quartz比Java的Timer优势在于Quartz允许调度一个工作在某个特定的时间或日期执行。
使用Quartz有两种方式实现
- 任务类继承QuartzJobBean
- 在配置文件中定义任务类和要执行的方法(借助:MethodInvokingJobDetailFactoryBean)
Spring实现调度器基本步骤
第一步:创建一个用于指定执行任务的QuartzJobBean子类
QuartzJobBean实现org.quartz.Job接口。QuartzJobBean子类应当覆盖executeInternal()方法,在executeInternal()方法中定义预定的时刻应执行动作(这一步是指明做什么)
参考代码如下:CustomerQuartzJobBean.java
package www.enfp.cc.springquartz;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class CustomerQuartzJobBean extends QuartzJobBean
{
@Override
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException
{
//指定需要执行的任务,这里仅仅是输出当前时间
System.out.println("执行调度任务: (当前时间:" + new Date() + ")");
}
}
第二步:在配置文件中进行调度器的相关配置(beans.xml)
1.配置执行工作<做什么>
JobDetailBean是Quartz的JobDetail的子类,通过jobClass属性来设置一个Job对象,将第一步的QuartzJobBean的子类的全路径传给JobDetailBean的jobClass属性
参考代码如下:
<!-- 配置执行工作(做什么) -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>www.enfp.cc.springquartz.CustomerQuartzJobBean</value>
</property>
</bean>
2.触发器Trigger的配置(配置执行时间和执行哪个工作)<什么时间做什么>
Quartz的Trigger类描述了调度时机和频度,Spring提供了两个触发器:SimpleTriggerBean、CronTriggerBean。
- SimpleTriggerBean用来指定一个工作运行频度,以及(可选地)在第一次运行之前等待时间。缺点是该触发器只能指定工作执行频度,而不能准确指定何时运行
- CronTriggerBean能更精确地控制任务的运行时间。如每晚8点发送电子邮件。
(1).使用SimpleTriggerBean调度器(属性)介绍
- jobDetail:定义工作(做什么)
- startDelay:服务启动后的时间延迟,单位毫秒
- repeatInterval:重复执行任务的时间间隔,单位毫秒
参考代码如下:
<!-- 执行效果:启动任务6秒后执行任务,并且每个4秒执行一次 -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!-- 指定任务(做什么) -->
<property name="jobDetail">
<ref bean="jobDetail" />
</property>
<!-- 服务启动后延迟多少时间执行,单位毫秒 -->
<property name="startDelay" value="6000"></property>
<!-- 重复执行任务的时间间隔,单位毫秒 -->
<property name="repeatInterval" value="4000"></property>
</bean>
(2).使用CronTriggerBean调度器(属性)介绍
- jobDetail:定义工作(做什么)
- cronExpression:cron表达式(指定执行时间)
一个cron表达式有至少6个(也可能是7个)由空格分隔的时间元素。从左至右,这些元素的定义如下
- 参数1:秒 0 - 59
- 参数2:分钟 0-59
- 参数3:小时 0-23
- 参数4:月份中的日期 1-31
- 参数5:月份 1-12或JAN-DEC
- 参数6:星期中的日期 1-7或SUN-SAT
- 参数7:年份1970-2099
注意: 每一个元素都可显式规定一个值(如6),一个区间(如9-12),一个列表(如9,11,13)或一个通配符(如*)。“月份中的日期”和“星期中的日期”互斥,应通过设置一个问号(?)来表明你不想设置的那个字段
参考代码如下:
<!-- (触发器的配置)配置执行时间(或间隔)和执行哪个工作(什么时间做什么) -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<!-- (做哪个工作) -->
<property name="jobDetail" ref="jobDetail"></property>
<!-- 配置cron表达式(什么时间做) -->
<property name="cronExpression" value="0 * 11 * * ?"></property>
</bean>
(3).启动触发器
使用Spring的SchedulerFactoryBean类可使用list表示启动多个触发器
参考代码如下:
<!-- 启动触发器 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<!-- 可以启动多个触发器,所以采用list标签 -->
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
第三步:测试
1.web应用中使用(在web.xml文件加载beans.xml)
2.在java 应用中使用ClassPathXmlApplicationContext类加载beans.xml
参考代码如下:SpringQuartzTest.java
package www.enfp.cc.springquartz;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringQuartzTest
{
public static void main(String[] args)
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"beans.xml");
}
}
补充:
常见一些cron表达式的例子:
- "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触发
- 每天早上6点
- 0 6 * * *
- 每两个小时
- 0 */2 * * *
- 晚上11点到早上8点之间每两个小时,早上八点
- 0 23-7/2,8 * * *
- 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
- 0 11 4 * 1-3
- 1月1日早上4点
- 0 4 1 1 *
来源:oschina
链接:https://my.oschina.net/u/2683971/blog/741873