Spring支持的Quartz程序调度

 开发时有时会有这样一种需求,定期计算某些数据或者执行某些程序进行操作,这种程序就是平时所说的批处理。批处理为应用分时段处理提供支持,减轻应用程序的负担,比如数据统计工作往往放在凌晨执行,这是服务器压力不大,使用者不多,是进行此类操作的最佳时段。白天人们使用时就能看到处理的结果了。 
    批处理程序的执行思路是先创建执行定时任务,然后对定时任务进行调度执行。 
    Java中的Timer类为批处理程序运行提供支持,要求扩展java.util.Timer类。Spring也支持Timer方式的调度,但是用过Quartz之后还是感觉Quartz更顺手,扩展性更强。但Quartz使用的定时方式是CRON表达式,这部分内容网上也很多,难度不大。 
    先搭建一个开发环境,很简单。运用了Java EE的分层结构,但测试时只是单机运行,下面我们一一来看。 


 
    我们在Sercice类中定义业务操作的基本方法,比如数据库操作,计算等,这里是我们具体执行业务逻辑的地方,为了说明问题,就打印一句话,如下: 

package org.ourpioneer.service;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

/**

 * 调度程序业务处理类

 * 

 * @author Sarin

 * 

 */

public class QuartzService {

private static final Logger logger = LoggerFactory

.getLogger(QuartzService.class);

 

public QuartzService() {

logger.debug("Construct QuartzService");

}

 

public void insertIntoDB() {

logger.debug("Run Insert Method");

}

}

 

为了结合Spring展示实例化类和方法调用顺序,这里在构造方法中也打印log。业务类很简单,定义操作的方法就行了。 
    调用Service的类是Job类,就是调度程序调度的类,每个调度称为一个Job,很形象,我们来看看: 

 

package org.ourpioneer.quartz.job;

 

import org.ourpioneer.service.QuartzService;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

/**

 * 调度任务

 * 

 * @author Sarin

 * 

 */

public class QuartzJob {

private static final Logger logger = LoggerFactory

.getLogger(QuartzJob.class);

// 业务类注入

private QuartzService quartzService;

 

public void setQuartzService(QuartzService quartzService) {

this.quartzService = quartzService;

logger.debug("QuartzService Injection");

}

 

public QuartzJob() {

logger.debug("Construct QuartzJob");

}

 

/**

* 目标执行方法

*/

public void execute() {

// 调度执行程序

quartzService.insertIntoDB();

logger.debug("Run QuartzJob");

}

}

 

Job类可以是一个简单的POJO,方法名都是随意定的,它们都是可以在Spring中配置的,Job类调用了Service类的业务方法,那么要将Service类注入。而Job类要被调度程序调度运行。 
    要运行调度程序,就要在Spring容器中实例化调度程序,这在Java EE程序运行时,因为容器是时时运行的,只要加载了响应的配置文件即可,而我们单机测试,要手工启动程序,启动Spring的方法很简单: 

 

package org.ourpioneer.quartz.app;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

/**

 * 任务调度测试类

 * 

 * @author Sarin

 * 

 */

public class QuartzApp {

private static final Logger logger = LoggerFactory

.getLogger(QuartzApp.class);

 

public QuartzApp() {

logger.debug("Construct QuartzApp");

}

 

public static void main(String[] args) {

new ClassPathXmlApplicationContext("classpath:spring/quartz.xml");

logger.debug("Run QuartzApp");

}

}

 

 

 

 

package org.ourpioneer.quartz.app;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

/**

 * 任务调度测试类

 * 

 * @author Sarin

 * 

 */

public class QuartzApp {

private static final Logger logger = LoggerFactory

.getLogger(QuartzApp.class);

 

public QuartzApp() {

logger.debug("Construct QuartzApp");

}

 

public static void main(String[] args) {

new ClassPathXmlApplicationContext("classpath:spring/quartz.xml");

logger.debug("Run QuartzApp");

}

}

 

 

使用类路径下的XML加载方式,找到配置文件quartz.xml,来启动Spring容器。下面就剩下Spring的配置了,我们逐条来看: 

 

<!-- Service配置 -->

<bean id="quartzService" 

class="org.ourpioneer.service.QuartzService"></bean>

 

 我们将Service放到Spring容器中,它会随着Spring容器加载而实例化,实现控制反转。下面是调度Job的定义: 

 

<!-- 定义调度对象和调用的方法 -->

<bean id="quartzJob"

class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

<property name="targetObject">

<bean class="org.ourpioneer.quartz.job.QuartzJob">

<property name="quartzService" ref="quartzService" />

</bean>

</property>

<property name="targetMethod">

<value>execute</value>

</property>

</bean>

 

  调度对象是targetObject,在其中注入我们自定义的Job,而Job依赖quartzService,那么不能忘记注入它。下面是targetMethod设置,就是调度的方法名,前面写的是execute,这里一样。所以这就体现了配置的灵活性。 
    调度程序有了,那么要定时执行,怎么来告诉控制程序来执行呢?监听时间,没错,这里使用的就是这种机制,不过不是监听器,监听器是监听事件的发生,而不能监听时间的到达,这里就是触发器,但和数据库的触发器不同,数据库的触发器还是监听了数据操作的事件,而不是时间。定点触发调度程序,要配置触发器: 

 

<!-- 配置触发器 -->

<bean id="QuartzCornTrigger" 

class="org.springframework.scheduling.quartz.CronTriggerBean">

<property name="jobDetail">

<ref local="quartzJob" />

</property>

<!-- 触发时间(使用cron表达式) -->

<property name="cronExpression">

<value>0/5 * * * * ?</value>

</property>

</bean>

 

   触发器中注入了调度的Job,就是我们上面定义的quartzJob,接着设置了触发的时间,使用了CRON表达式,下面简单说说CRON表达式。 
    CRON表达式使用7个域来表示时间,以空格分隔开,最后一个域是年,这个是可选的,示例中就没有。剩下的六个域依次是秒,分,小时,每月的几号,月份,一周中的周几。*号表示通配符,匹配所有值。?号也是通配符,但是只能匹配每月的几号和一周的周几,而且这两个不能同时匹配。/表示增量,就是每隔多少触发一次。每个域可以是固定数值,也可以是范围(如1-5)或一个列表(如1,3,5),好了,就这么简单。示例中的含义就是从0秒开始每隔5秒执行一次,而分,小时等都是随意的,所以它会在0,5,10,15…这样的秒数时执行。要配置每天凌晨4点执行的触发器就是0 0 4 * * ?了。 
    Spring的配置就结束了,非常简单,我们来看一下bean的关系图,更直观一点: 
 
    这里就看出了它们之间的依赖关系,下面我们来测试,启动主函数运行: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值