在Spring中使用Quartz
Spring 提供了几个帮助类用于在应用中做调度,包括JDK Timer类和OpenSymphony Quartz Scheduler两种.
Quartz基础
Quartz包括五种主要结构用于实现调度:
- Job接口
- JobDetail类
- Trigger 抽象类
- Scheduler接口
- SchedulerFactory 接口
Job接口表示一个作业(job)。一个作业专注做一件事。它的API非常简洁。只有一个execute方法,该方法在作业被执行时有Quartz调度。该方法有一个JobExecuteContext参数,可以通过该参数给execute()方法传递有用信息。
public interface Job{ void execute(JobExecuteContext ctx); }
一些数据可以通过JobDataMap传递给作业。如果一个JobDataMap被注册到JobDetail中,就能够在作业中通过
JobExecuteContext来访问。JobDetail用来描述一个特定Job的信息。Job通过触发器(Trigger)触发。Quartz提
供了集中Trigger的实现,如SimpleTrigger和CronTrigger。SimpleTrigger类似一个简单时钟,你可以定义开始是
建,结束时间,重复次数,重复周期。CronTrigger类似Linux系统中的cron。CronTrigger的设置可以非常详细,如在每个月最后
一个周五的上午10:15执行作业。需要注意的是Trigger和Job是具名的,可以被赋值给一个组,在同一组内不能出现同名。你可以对一个组创建一个
触发器,在该组内的所有Job都将会执行。
SchedulerFactory 用于获得Scheduler实例,可以用于注册作业和触发器。
实现一个简单的实例:每十秒钟打印一次欢迎。
首先实现一个作业:
public class SimpleJob implements Job { @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("[JOB] Welcome to Quartz!"); } }
定义一个Scheduler,注册触发器和作业:
public class SimpleSchedule { public static void main(String[] args) { SchedulerFactory factory=new StdSchedulerFactory(); try { Scheduler scheduler = factory.getScheduler(); scheduler.start(); JobDetail jobDetail = new JobDetail("SimpleJob",null, SimpleJob.class); Trigger simplerTrigger = TriggerUtils.makeSecondlyTrigger(10); simplerTrigger.setName("SimpleTrigger"); scheduler.scheduleJob(jobDetail, simplerTrigger); }catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
执行过后,每十秒输出[JOB] Welcome to Quartz!
Spring中的Quartz
Spring中的Quartz API位于org.springframework.scheduling.quartz包中。主要类结构包括:
- QuartzJobBean 抽象类
- JobDetailBean
- SimpleTriggerBean
- CronTriggerBean
- SchedulerFactoryBean
- MethodInvokingDetailFactoryBean
很明显对应实现Quartz中相应的接口。QuartzJob实现Job,JobDetailBean继承JobDetail。
SimpleTriggerBean和CronTriggerBean继承自相应的Trigger。
MethodInvokingJobDetailFactoryBean用于在类中调用任何对象的方法。
声明Job
JobDetailBean用于声明作业。可以为其设置作业名,以及需要的数据。
<bean name="simpleJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="com.alibaba.jiang.learn.quartz.SimpleJob" /> <property name="jobDataAsMap"> <map> <entry key="message" value="Welcome to Quartz" /> </map> </property> </bean>
实现Job类:
public class SimpleJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException { String message = ctx.getJobDetail().getJobDataMap().getString("message"); System.out.println(message); } }
还可以通过setter注入的方式注入message。
声明触发器:
<bean name="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="simpleJob"/> <property name="startDelay" value="0"/> <property name="repeatInterval" value="10000"/> </bean>
声明调度器,设置Job和Trigger:
<bean name="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger"/> </list> </property> </bean>
所有都设置好后,可以通过加载Context,调度器将自动执行:
public class SimpleSpringQuartz { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); } }
使用MethodInvokingJobFactoryBean
上面的范例使用的是Quartz Job,事实上在Spring中可以使用自定义Pojo Bean,无须继承自QuartzJobBean。
首先声明一个PojoBean
<bean name="welcomeBean" class="com.alibaba.jiang.learn.quartz.WelcomeBean"> <property name="message" value="Welcome to Quartz Method"/> </bean>
对应的Pojo Bean:
public class WelcomeBean { private String message; public void setMessage(String message) { this.message = message; } public void welcome(){ System.out.println(message); } }
声明MethodInvokingJobDetailFactoryBean:
<bean name="methodInvokingJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="welcomeBean"/> <property name="targetMethod" value="welcome"/> </bean> <bean name="methodTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="methodInvokingJob" /> <property name="startDelay" value="0"/> <property name="repeatInterval" value="10000"/> </bean>
注意
一个触发器只能触发一个Job,不过一个Job可以有多个Trigger触发,这回带来并发问题。在Quartz中,如果你不想并发执行一个同一个 Job,你可以实现StatefulJob,而不是Job。在Spring中如果使用 MethodInvokingJobDetailFactoryBean,可以通过设置concurrent="false"属性来实现。
尾注
在Spring中使用Quartz而不是单独的一个应用的好处包括:
- 将所有的任务调度设置放在同一个地方,是任务易于维护。
- 只对Job编码,Trigger和Scheduler可以通过配置设置
- 可以使用Pojo Java Bean执行job,而无需实现Job接口
blog comments powered by Disqus