天天看點

在Spring中使用JDK定時器實作排程任務

本文探讨Spring如何內建JDK的Timer定時器,實作計劃執行任務。

有時候,需要執行一些無使用者互動的程式,就像在指定的時間間隔背景運作程序那樣。比如,防毒軟體可以每隔2天就在背景運作一次。又比如某些程式每天都要連接配接一次伺服器,檢視有沒有更新。

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

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 id="scheduledConnectionCheckTimerTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">  

        property name="delay" value="2000" />  

        property name="period" value="30000" />  

        property name="timerTask" ref="connectionCheckTimerTask" />  

    bean class="org.springframework.scheduling.timer.TimerFactoryBean">  

        property name="scheduledTimerTasks">  

            list>  

                ref bean="scheduledConnectionCheckTimerTask" />  

        property>  

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" />  

    property>  

用戶端程式會載入應用程式的上下文。一旦上下文被載入,服務對象、定時器任務對象、排程的定時器任務對象都會被載入并連線。下面我們繼續介紹觸發器Bean是如何觸發定時器任務的執行,網際網路連接配接在每隔30秒運作一次。

Listing 4: Client.java

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