Quartz是一个任务调度框架,由Java语言开发,可以用来做一些定时发送,监听事件等工作。
例如:让一个程序每天晚上12点执行一次。或者每隔5秒执行一次。
jar: org.quartz-scheduler包下
Quartz完成调度需要3步
JobDetail:告诉调度器要做什么。
Trigger:告诉调度器什么时候做。
Scheduler:准备妥了就从这里start
下面就是一个简单的spring 整合quartz的实例。
简单实现
先看JobDetail部分:写一个类实现Job接口,重写execute()方法,在该方法中写要执行的逻辑,(告诉调度器要做什么)
public class UpdateProductJob implements Job{
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
System.out.print("我来检查啦")
}catch (Exception e){
System.out.println(e);
}
}
}
然后是配置xml文件。
<!--quartz-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.config.quartz.UpdateProductJob"></property>
</bean>
<!--执行时间表达方式一-->
<!--<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">-->
<!--<property name="jobDetail" ref="jobDetail"></property>-->
<!--<property name="startDelay" value="10000"></property><!–延迟10s–>-->
<!--<property name="repeatInterval" value="5000"></property>-->
<!--</bean>-->
<!--执行时间表达方式二-->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0 59 23 ? * *" />
</bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
从上面可以看到有两个Trigger分别是simpleTrigger和cronTrigger,这是两种表达执行时间的方式。
simpleTrigger是比较简单的方法,
<property name="repeatInterval" value="5000"></property>表示间隔5秒执行一次
而cronTrigger可以表达一些比较复杂的时间格式
<property name="cronExpression" value="0 59 23 ? * *" />表示每天23点59分执行一次
具体的语法请搜索cron表达式,有些网站提供了自动生成cron表达式的功能
比如http://cron.qqe2.com/ or http://www.cronmaker.com/
解决spring注入问题
在spring框架中会经常用到IOC,那么在上面的execute()方法中不避免的也会用到注入,但是对于新手来说会遇到注入的接口会是null。
解决这个问题有两个方法:
1.使用ApplicationContex对象加载applicationContext.xml文件注入UserDaoI接口,但是这个方法不好的一点是每当用一个接口就要写一个,比较麻烦。
ApplicationContext content =
new ClassPathXmlApplicationContext("classpath:META-INF/applicationContext.xml");
userDaoI = content.getBean(UserDaoI.class);
2.第二个方法比较好,先写一个类继承AdaptableJobFactory 抽象方法,不需要任何改动
@Service("jobFactory")
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
2.2然后将这个类添加到配置文件里。
<bean id="jobFactory" class="com.config.quartz.JobFactory"></bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobFactory"></property>
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
最后完整的配置信息是:
<!--quartz-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.config.quartz.UpdateProductJob"></property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0 59 23 ? * *" />
</bean>
<bean id="jobFactory" class="com.config.quartz.JobFactory"></bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobFactory"></property>
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
JobDetail部分就可以这样写了
@Service
public class UpdateProductJob implements Job{
@Autowired
ArticleService articleService;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
articleService.updateArticleType();
}catch (Exception e){
System.out.println(e);
}
}
}
Quartz轮训方式
Quartz轮训任务,需要配置一个参数,这个参数来控制Job任务是否并行,这个参数是concurrent。默认是true,如果concurrent设为true,到了指定的时间就如去执行,不管上一次有没有执行完。
<bean id="transmitTask"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref bean="transTaskBusiness" />
</property>
<property name="targetMethod">
<value>execute</value>
</property>
<property name="concurrent">
<value>false</value>
</property>
</bean>
任务监听器
TriggerListeners
and JobListeners
两个接口分别是触发器相关的监听接口和作业相关监听接口。
用来监听监听点
之前,之中,之后需要处理的事情。
此外,也可以直接继承JobListenerSupport
or TriggerListenerSupport
并且在配置文件添加以下内容来生效监听器:
<!--全局任务监听器 -->
<bean id="scheduleJobListener"
class="com.mashu.services.task.manager.ScheduleJobListener">
<property name="name" value="scheduleJobListener"></property>
</bean>
除了可以配置全局的,也可以根据业务按个,按组配置监听器。
Quartz 2.3.0