本文探讨Spring如何集成JDK的Timer定时器,实现计划执行任务。
有时候,需要执行一些无用户交互的程序,就像在指定的时间间隔后台运行进程那样。比如,杀毒软件可以每隔2天就在后台运行一次。又比如某些程序每天都要连接一次服务器,查看有没有更新。
本文探讨Spring如何集成JDK的Timer定时器,实现计划执行任务。
假设我们想写一个服务,此服务周期性的检查互联网连接,并用日志记录连接的状态。让我们假定此服务是全天候运行的,且每隔30秒执行一次。
所需要的JAR包如下:
log4j-1.2.13.jar
commons-logging-1.1.1.jar
spring-beans-3.2.4.RELEASE.jar
spring-context-3.2.4.RELEASE.jar
spring-context-support-3.2.4.RELEASE.jar
spring-core-3.2.4.RELEASE.jar
spring-expression-3.2.4.RELEASE.jar
Listing 1: CheckInternetConnectionService.java
上面的代码很简单,doCheck()方法检查互联网连接是否有效。
Listing 2: CheckInternetConnectionWithTimerTask
此类继承了java.util.TimerTask类。
重写了run()方法,可以执行任意操作。这里是调用互联网连接检查。
注意定时器任务依赖于连接服务对象。稍后,我们将看到怎样连线这两个对象。
Listing 3: timer.xml
以上配置文件的细节:
"connectionCheckService"这个Bean表示互联网连接服务。
"connectionCheckTimerTask"这个Bean定义了定时器任务。由于此定时器任务依赖于"connectionCheckService"这个Bean,故通过配置进行注入。
下面的代码是从Spring框架中声明定时器任务的调度对象:
org.springframework.scheduling.timer.ScheduledTimerTask这个类提供了对定时任务调度执行的支持。
属性delay的单位是毫秒,它指定任务执行前需要延时多少时间。2000意味着延时2秒开始执行任务。
第二个属性period的单位也是毫秒,它表示任务每隔多少时间就重复执行一次。30000这个值表示每隔30秒执行一次。
最后一个属性是timerTask,它指定实际要执行的任务。
触发调度任务是通过TimerFactoryBean进行的。它可以指定待调度的任务对象列表,尽管这里只有1个待调度的任务对象。
Listing 4: Client.java
运行Client.java,可以看到每隔30秒定时器任务就调度执行一次。
执行结果如下:
有时候,需要执行一些无用户交互的程序,就像在指定的时间间隔后台运行进程那样。比如,杀毒软件可以每隔2天就在后台运行一次。又比如某些程序每天都要连接一次服务器,查看有没有更新。
本文探讨Spring如何集成JDK的Timer定时器,实现计划执行任务。
一、Spring框架集成JDK的Timer
JDK的Timer任务对象提供了在指定时间执行任何任务的功能。我们来看下面的例子:假设我们想写一个服务,此服务周期性的检查互联网连接,并用日志记录连接的状态。让我们假定此服务是全天候运行的,且每隔30秒执行一次。
所需要的JAR包如下:
log4j-1.2.13.jar
commons-logging-1.1.1.jar
spring-beans-3.2.4.RELEASE.jar
spring-context-3.2.4.RELEASE.jar
spring-context-support-3.2.4.RELEASE.jar
spring-core-3.2.4.RELEASE.jar
spring-expression-3.2.4.RELEASE.jar
二、写服务类
下面的类实现了互联网连接检查。Listing 1: CheckInternetConnectionService.java
- package com.chszs;
- import java.net.URL;
- import java.net.URLConnection;
- import java.util.Date;
- public class CheckInternetConnectionService {
- public void checkConnection(){
- if(doCheck()){
- System.out.println(new Date() + "Internet connection available");
- }else{
- System.out.println(new Date() + "Internet connection not available");
- }
- }
- private boolean doCheck(){
- URL urlObject = null;
- URLConnection urlConnection = null;
- try{
- urlObject = new URL("http://www.baidu.com");
- urlConnection = urlObject.openConnection();
- urlConnection.getContent();
- return true;
- }catch(Exception e){
- return false;
- }
- }
- }
上面的代码很简单,doCheck()方法检查互联网连接是否有效。
三、封装定时器任务服务
下面我们写一个服务,实现定时任务。代码如下:Listing 2: CheckInternetConnectionWithTimerTask
- package com.chszs;
- import java.util.TimerTask;
- public class CheckInternetConnectionWithTimerTask extends TimerTask{
- private CheckInternetConnectionService service;
- public CheckInternetConnectionService getService(){
- return service;
- }
- public void setService(CheckInternetConnectionService service){
- this.service = service;
- }
- @Override
- public void run() {
- service.checkConnection();
- }
- }
此类继承了java.util.TimerTask类。
重写了run()方法,可以执行任意操作。这里是调用互联网连接检查。
注意定时器任务依赖于连接服务对象。稍后,我们将看到怎样连线这两个对象。
四、配置
至今,我们还没有指定执行的时间间隔。Spring提供了这样的配置支持。下面我们来看看该如何配置:Listing 3: timer.xml
- xml version="1.0" encoding="UTF-8"?>
- beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd">
- bean id="connectionCheckService" class="com.chszs.CheckInternetConnectionService">
- bean>
- bean id="connectionCheckTimerTask" class="com.chszs.CheckInternetConnectionWithTimerTask">
- property name="service" ref="connectionCheckService" />
- bean>
- bean id="scheduledConnectionCheckTimerTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
- property name="delay" value="2000" />
- property name="period" value="30000" />
- property name="timerTask" ref="connectionCheckTimerTask" />
- bean>
- bean class="org.springframework.scheduling.timer.TimerFactoryBean">
- property name="scheduledTimerTasks">
- list>
- ref bean="scheduledConnectionCheckTimerTask" />
- list>
- property>
- bean>
- beans>
以上配置文件的细节:
"connectionCheckService"这个Bean表示互联网连接服务。
"connectionCheckTimerTask"这个Bean定义了定时器任务。由于此定时器任务依赖于"connectionCheckService"这个Bean,故通过配置进行注入。
下面的代码是从Spring框架中声明定时器任务的调度对象:
- bean id="scheduledConnectionCheckTimerTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
- property name="delay" value="2000" />
- property name="period" value="30000" />
- property name="timerTask" ref="connectionCheckTimerTask" />
- bean>
org.springframework.scheduling.timer.ScheduledTimerTask这个类提供了对定时任务调度执行的支持。
属性delay的单位是毫秒,它指定任务执行前需要延时多少时间。2000意味着延时2秒开始执行任务。
第二个属性period的单位也是毫秒,它表示任务每隔多少时间就重复执行一次。30000这个值表示每隔30秒执行一次。
最后一个属性是timerTask,它指定实际要执行的任务。
触发调度任务是通过TimerFactoryBean进行的。它可以指定待调度的任务对象列表,尽管这里只有1个待调度的任务对象。
- bean class="org.springframework.scheduling.timer.TimerFactoryBean">
- property name="scheduledTimerTasks">
- list>
- ref bean="scheduledConnectionCheckTimerTask" />
- list>
- property>
- bean>
五、客户端
客户端程序会载入应用程序的上下文。一旦上下文被载入,服务对象、定时器任务对象、调度的定时器任务对象都会被载入并连线。下面我们继续介绍触发器Bean是如何触发定时器任务的执行,互联网连接在每隔30秒运行一次。Listing 4: Client.java
- package com.chszs;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Client {
- public static void main(String[] args){
- ApplicationContext ctx = new ClassPathXmlApplicationContext("timer.xml");
- }
- }
运行Client.java,可以看到每隔30秒定时器任务就调度执行一次。
执行结果如下:
- Sun Aug 11 21:08:26 CST 2013Internet connection available
- Sun Aug 11 21:08:56 CST 2013Internet connection available
- Sun Aug 11 21:09:26 CST 2013Internet connection available
- Sun Aug 11 21:09:56 CST 2013Internet connection available