Quartz是一个开放源码项目,专注于任务调度器,提供了极为广泛的特性如持久化任务,集群和分布式任务等。
Spring对Quartz的集成与其对JDK Timer的集成在任务、触发器和调度计划的声明式配置方面等都非常相似。
Quartz的核心由两个接口和两个类组成:Job和Scheduler接口,JobDetail和Trigger类。
不同于JDK Timer,任务不是从实现一个Job接口的类实例开始运行,实际上Quartz在需要的时候才创建job类实例。
可以使用JobDetail类来包装任务状态,并传递一个信息给Job,或在一个Job的多次执行过程之间保存信息。
二、Quartz任务调度
1. 简单任务调度
在Quartz中创建一个任务并执行,只需要实现Job接口类,在其execute()方法中处理你的业务逻辑。
package quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class TestJob implements Job
{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
// 这里实现业务逻辑
String name = context.getJobDetail().getJobDataMap().getString("name");
System.out.println("job executing..." + name);
}
}
package quartz;
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
/**
* 应用于application的定时机制
* <功能详细描述>
*
* @version [版本号, 2013-12-16]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class QuartzTest
{
public static void main(String[] args)
{
QuartzTest test = new QuartzTest();
try
{
test.startSchedule();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void startSchedule() throws Exception
{
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail jobDetail = new JobDetail("testJob", Scheduler.DEFAULT_GROUP, TestJob.class);
//使用JobDetail传递数据
//jobDetail.getJobDataMap().put("name", "testJob");
// 结束时间
long end = System.currentTimeMillis() + 90000L;
// 执行3+1次,每3秒执行一次,到90秒后结束
/*
SimpleTrigger(parm1, parm2, parm3, parm4, parm5,parm6);
parm1 String 触发器名
parm2 String 组名
parm3 Date 开始时间
parm4 Date 结束时间
parm5 int 允许的最大次数(SimpleTrigger.REPEAT_INDEFINITELY 为无限次)
parm6 Long 时间间隔
*/
SimpleTrigger trigger = new SimpleTrigger("test", null, new Date(), new Date(end), 3, 3000L);
scheduler.scheduleJob(jobDetail, trigger);
//开始
scheduler.start();
}
}
result:
job executing...null
job executing...null
job executing...null
job executing...null
2. 使用JobDetail传递数据
每个JobDetail实例都有关联的JobDataMap实例,它实现了Map接口并允许通过键值来传递任务相关的数据。
任务也可以修改JobDataMap中的数据,在同一任务的多次执行之间传递数据。
public class TestJob implements Job
{
/* @Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
// 这里实现业务逻辑
String name = context.getJobDetail().getJobDataMap().getString("name");
System.out.println("job executing..." + name);
}*/
@Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
Map properties = context.getJobDetail().getJobDataMap();
System.out.println("Current Fire Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(context.getFireTime()));
System.out.println("Next Fire Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(context.getNextFireTime()));
System.out.println(properties.get("name"));
}
}
reslut:
Current Fire Time: 2014-02-08 16:33:18
Next Fire Time: 2014-02-08 16:33:21
testJob
Current Fire Time: 2014-02-08 16:33:21
Next Fire Time: 2014-02-08 16:33:24
testJob
Current Fire Time: 2014-02-08 16:33:24
Next Fire Time: 2014-02-08 16:33:27
testJob
Current Fire Time: 2014-02-08 16:33:27
3. 使用CronTrigger
CronTrigger提供了对复杂触发器的支持。
package quartz;
import java.util.Calendar;
import java.util.Map;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.HolidayCalendar;
public class CronWithCalendarScheduling
{
public static void main(String[] args) throws Exception
{
Calendar cal = Calendar.getInstance();
cal.set(2010, Calendar.OCTOBER, 31);
HolidayCalendar calendar = new HolidayCalendar();
calendar.addExcludedDate(cal.getTime());
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.addCalendar("calendar", calendar, true, false);
JobDetail jobDetail = new JobDetail("test", Scheduler.DEFAULT_GROUP, TestJob.class);
Map map = jobDetail.getJobDataMap();
map.put("name", "This is a message from Quartz");
表示每分钟第9秒开始,每3秒执行一次
String cronExpression = "0/3 * * * * ?";
Trigger trigger = new CronTrigger("cronTrigger", Scheduler.DEFAULT_GROUP, cronExpression);
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
result:
job executing...This is a message from Quartz
job executing...This is a message from Quartz
job executing...This is a message from Quartz
job executing...This is a message from Quartz
....................
cronExpression将在转载的下一篇详细阐述。
三. Spring对Quartz调度的支持
applicationContext-init.xml 定时器片段:
<!-- 引入annotation -->
<context:annotation-config />
<!-- 让spring自动扫描指定包下面注解 -->
<context:component-scan base-package="com.*" />
<bean id="emailJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 调用的类 -->
<property name="targetObject">
<ref bean="emailReportJob" />
</property>
<!-- 调用类中的方法 -->
<property name="targetMethod">
<value>inputStr</value>
</property>
</bean>
<!-- Spring提供的触发器: CronTriggerBean指定工作的准确运行时间 -->
<bean id="emailReportJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="emailJob"></property>
<property name="cronExpression">
<value>9/3 * * * * ?</value>
</property>
</bean>
<!-- 启动定时器 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
lazy-init="true">
<property name="triggers">
<list>
<ref bean="emailReportJobTrigger" />
</list>
</property>
</bean>
代码片段:
@Component("emailReportJob")
public class EmailReportJob extends QuartzJobBean
{
/** {@inheritDoc} */
@Override
protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException
{
LogUtils.runInfo("executeInternal is runing.....");
}
public void inputStr()throws JobExecutionException
{
LogUtils.runInfo("inputStr is runing.....");
}
}