做开发的时候很多时候面临着一个问题,那就是定时任务的问题,比如我之前做的搜索引擎系统,新闻模块每小时更新一次,视频每2小时更新一次,汽车频道没一周更新一次;显然这种更新不应该由人工来完成,一个是工作量非常大,二个是显得很没有技术含量;在这方面spring提供了ScheduledTimerTask,就是通常所说的任务了;把配置好的任务(ScheduledTimerTask)塞到调度器TimerFactoryBean里面就可以了,当然了TimerFactoryBean可以同时执行多个任务;看了一下spring的源代码,ScheduledTimerTask和TimerFactoryBean也很简单,ScheduledTimerTask就是对java.util包下的TimerTask做了简单的封装,而TimerFactoryBean也是对java.util包下的Timer包装一下,现在把源代码放上来看一下:
package org.springframework.scheduling.timer; import java.util.TimerTask; public class ScheduledTimerTask { private TimerTask timerTask; private long delay = 0L; private long period = 0L; private boolean fixedRate = false; public ScheduledTimerTask(TimerTask timerTask) { this.timerTask = timerTask; } public ScheduledTimerTask(TimerTask timerTask, long delay) { this.timerTask = timerTask; this.delay = delay; } public ScheduledTimerTask(TimerTask timerTask, long delay, long period, boolean fixedRate) { this.timerTask = timerTask; this.delay = delay; this.period = period; this.fixedRate = fixedRate; } public void setTimerTask(TimerTask timerTask) { this.timerTask = timerTask; } public TimerTask getTimerTask() { return this.timerTask; } public void setDelay(long delay) { this.delay = delay; } public long getDelay() { return this.delay; } public void setPeriod(long period) { this.period = period; } public long getPeriod() { return this.period; } public void setFixedRate(boolean fixedRate) { this.fixedRate = fixedRate; } public boolean isFixedRate() { return this.fixedRate; } }
以下是TimerFactoryBean的源代码:
package org.springframework.scheduling.timer; import java.util.Timer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; public class TimerFactoryBean implements FactoryBean, InitializingBean, DisposableBean { protected final Log logger; private ScheduledTimerTask[] scheduledTimerTasks; private boolean daemon; private Timer timer; public TimerFactoryBean() { this.logger = LogFactory.getLog(super.getClass()); this.daemon = true; } public void setScheduledTimerTasks(ScheduledTimerTask[] scheduledTimerTasks) { this.scheduledTimerTasks = scheduledTimerTasks; } public void setDaemon(boolean daemon) { this.daemon = daemon; } public void afterPropertiesSet() { this.logger.info("Initializing Timer"); this.timer = createTimer(this.daemon); for (int i = 0; i < this.scheduledTimerTasks.length; ++i) { ScheduledTimerTask scheduledTask = this.scheduledTimerTasks[i]; if (scheduledTask.getPeriod() > 0L) { if (scheduledTask.isFixedRate()) { this.timer.scheduleAtFixedRate(scheduledTask.getTimerTask(), scheduledTask.getDelay(), scheduledTask.getPeriod()); } else { this.timer.schedule(scheduledTask.getTimerTask(), scheduledTask.getDelay(), scheduledTask.getPeriod()); } } else { this.timer.schedule(scheduledTask.getTimerTask(), scheduledTask.getDelay()); } } } protected Timer createTimer(boolean daemon) { return new Timer(daemon); } public Object getObject() { return this.timer; } public Class getObjectType() { return Timer.class; } public boolean isSingleton() { return true; } public void destroy() { this.logger.info("Cancelling Timer"); this.timer.cancel(); } }
最后做一个小demo
步骤:
1开发任务类,也就是继承了java.util.TimerTask的类,并写好该类的run 方法,run方法里面就是要执行的业务逻辑
2 写好spring的application配置文件
package task; import java.util.Date; import java.util.TimerTask; public class NewsTimeTask extends TimerTask{ private int i=0; public void run() { System.out.println("开始进行第--"+(++i)+"--次car---新闻的搜集--"+this.getClass().getName()+"/////////"+new Date()); } }
package task; import java.util.Date; import java.util.TimerTask; public class VideoTimerTask extends TimerTask { private int i=0; public void run() { System.out.println("开始进行第--"+(++i)+"--次car---视频的搜集--"+this.getClass().getName()+"/////////"+new Date()); } }
package task; import java.util.Date; import java.util.TimerTask; public class CarTimerTask extends TimerTask{ private int i=0; public void run(){ System.out.println("开始进行第--"+(++i)+"--次car---汽车的搜集--"+this.getClass().getName()+"/////////"+new Date()); } }
applicationContext.xml配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" ":/spring-beans.dtd"> --> <beans> <bean id="newsTask" class="task.NewsTimeTask"></bean> <bean id="videoTask" class="task.VideoTimerTask"></bean> <bean id="carTask" class="task.CarTimerTask"></bean> <bean id="newsScheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <!-- 系统启动后60秒开始执行 --> <property name="delay" value="60000"></property> <!-- 每60秒执行一次 --> <property name="period" value="60000"></property> <property name="timerTask" ref="newsTask"></property> </bean> <bean id="videoScheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <property name="delay" value="60000"></property> <property name="period" value="180000"></property> <property name="timerTask" ref="videoTask"></property> </bean> <bean id="carScheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <property name="delay" value="60000"></property> <property name="period" value="300000"></property> <property name="timerTask" ref="carTask"></property> </bean> <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref bean="newsScheduledTask"/> <ref bean="videoScheduledTask"/> <ref bean="carScheduledTask"/> </list> </property> </bean> </beans>
只要启动spring之后任务就自动执行了,不在用做任务其他额外的工作!
程序的输出如下:
开始进行第--1--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:13:27 CST 2009 开始进行第--1--次car---视频的搜集--task.VideoTimerTask/////////Wed Jul 29 10:13:27 CST 2009 开始进行第--1--次car---汽车的搜集--task.CarTimerTask/////////Wed Jul 29 10:13:27 CST 2009 开始进行第--2--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:14:27 CST 2009 开始进行第--3--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:15:27 CST 2009 开始进行第--4--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:16:27 CST 2009 开始进行第--2--次car---视频的搜集--task.VideoTimerTask/////////Wed Jul 29 10:16:27 CST 2009 开始进行第--5--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:17:27 CST 2009 开始进行第--6--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:18:27 CST 2009 开始进行第--2--次car---汽车的搜集--task.CarTimerTask/////////Wed Jul 29 10:18:27 CST 2009 开始进行第--7--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:19:27 CST 2009 开始进行第--3--次car---视频的搜集--task.VideoTimerTask/////////Wed Jul 29 10:19:27 CST 2009 开始进行第--8--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:20:27 CST 2009 开始进行第--9--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:21:27 CST 2009 开始进行第--10--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:22:27 CST 2009 开始进行第--4--次car---视频的搜集--task.VideoTimerTask/////////Wed Jul 29 10:22:27 CST 2009 开始进行第--3--次car---汽车的搜集--task.CarTimerTask/////////Wed Jul 29 10:23:27 CST 2009 开始进行第--11--次car---新闻的搜集--task.NewsTimeTask/////////Wed Jul 29 10:23:27 CST 2009