这几天需要用到定时任务调度,开始准备用timer,后来经过别人介绍与spring集成的quartz,看了下更适合开发,因此转向quartz的学习,特此记录下来。
quartz使用起来及其方便,与spring整合配置,只需要写一个类继承QuartzJobBean,重写其executeInternal(JobExecutionContext arg0)即可,我们只需要将自己的逻辑代码写在该方法即可。一旦你配置好实现类并设定好调度时间,Quartz将密切注意剩余时间。当调度程序确定该是执行作业的时候,Quartz框架将调用你作业类上的executeInternal()方法并执行相应的任务。无需报告任何东西给调度器或调用任何特定的东西。仅仅执行任务和结束任务即可。如果配置你的作业在随后再次被调用,Quartz框架将在恰当的时间再次调用它。
quartz有三个核心概念,调度器、任务和触发器。三者关系简单来说就是,调度器负责调度各个任务,到了某个时刻或者过了一定时间,触发器触动了,特定任务便启动执行。概念相对应的类和接口有:
1)JobDetail:描述任务的相关情况,包括配置任务执行的类和方法。
2)Trigger:描述出发Job执行的时间触发规则。有SimpleTrigger和CronTrigger两个子类代表两种方式,一种是每隔多少分钟小时执行,则用SimpleTrigger;另一种是日历相关的重复时间间隔,如每天凌晨,每周星期一运行的话,通过Cron表达式便可定义出复杂的调度方案。
3)Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail要注册到Scheduler中才会生效,也就是让调度器知道有哪些触发器和任务,才能进行按规则进行调度任务。
quartz的配置一般有两种,一种是配置无参数的任务,就是一个普通方法,要求该执行任务的方法必须为无参方法,否则会报错。另一种是配置可传参方法,因为这里我需要给任务传递一些参数,所以采用第二种配置方法。
首先,需要下载quartz和spring对其提供支持的jar包。我这里采用的是quartz-2.2.1.jar,spring-context-support-4.2.4.RELEASE.jar,下载其他版本请注意包版本之间的兼容。
任务类配置:
<!-- 配置Job的bean -->
<bean id="myJob" class="com.wego.task.Syn_Scheduling"/>
JobDetail的配置
<!-- 配置jobDetail -->
<bean id="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 用到的Job实例 -->
<property name="jobClass" value="com.wego.task.Syn_Scheduling"/>
</bean>
Trigger的配置
<!-- 配置触发器Trigger -->
<bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="work_default_name"/>
<property name="group" value="work_default"/>
<property name="jobDetail" ref="myJobDetail"/>
<!-- 每天1点10分30执行 30 10 1 * * ? 每五秒执行一次 0/5 * * * * ? -->
<property name="cronExpression" value="0/30 * * * * ?"/>
</bean>
scheduler配置
<!-- 配置scheduler工厂 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers" ref="myTrigger"/>
<!-- 这里配置任务不随spring容器初始化而自动启动 -->
<property name="autoStartup" value="false"/>
</bean>
注意我标红的地方,因为我需要通过前台点击按钮触发任务启动,所以我设置了不随spring初始化而启动,一般情况下默认是随spring初始化自动启动任务的。手动启动任务需要下面:
Resource res = new ClassPathResource("beans.xml");
BeanFactory bf = new XmlBeanFactory(res);
Scheduler scheduler=(Scheduler)bf.getBean("scheduler");
try {
scheduler.start();//启动任务
} catch (SchedulerException e) {
e.printStackTrace();
}
任务类:
public class Syn_Scheduling extends QuartzJobBean{
@Override
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException {
}
}
完整的配置文件
<!-- quartz配置 -->
<!-- 配置Job的bean --><!-- com.wego.action.IndexAction -->
<bean id="myJob" class="com.wego.task.Syn_Scheduling"/>
<!-- 配置jobDetail -->
<bean id="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 用到的Job实例 -->
<property name="jobClass" value="com.wego.task.Syn_Scheduling"/>
</bean>
<!-- 配置触发器Trigger -->
<bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="work_default_name"/>
<property name="group" value="work_default"/>
<property name="jobDetail" ref="myJobDetail"/>
<!-- 每天1点10分30执行 30 10 1 * * ? 每五秒执行一次0/5 * * * * ? -->
<property name="cronExpression" value="0/30 * * * * ?"/>
</bean>
<!-- 配置scheduler工厂 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers" ref="myTrigger"/>
<!-- 这里配置任务不随spring容器初始化而自动启动 -->
<property name="autoStartup" value="false"/>
</bean>
action:
@Controller
@Scope("prototype")
public class IndexAction extends ActionSupport {
Resource(name = "organizeService")
private OrganizationService organizationService;
public void doTask(){
Resource res = new ClassPathResource("applicationContext.xml");
BeanFactory bf = new XmlBeanFactory(res);
Scheduler scheduler = (Scheduler) bf.getBean("scheduler");
try {
// 放入service对象
scheduler.getContext().put("organizationService",organizationService);
scheduler.start();
}catch (SchedulerException e){
e.printStackTrace();
}
}
}
任务类:
public class Syn_Scheduling extends QuartzJobBean{
private OrganizationService organizationService;
@Override
protected void executeInternal(JobExecutionContext arg0)throws JobExecutionException {
try {
organizationService= (OrganizationService) arg0.getScheduler().getContext().get("organizationService");
} catch (SchedulerException e1) {
e1.printStackTrace();
}
}
}