1. 程式人生 > >spring定時器及cron表示式

spring定時器及cron表示式

在Spring中有兩種流行配置:Java的Timer類和OpenSymphony的Quartz。 
1.Java Timer定時 
首先繼承java.util.TimerTask類實現run方法 
import java.util.TimerTask; 
public class EmailReportTask extends TimerTask{ 
    @Override 
    public void run() { 
        ... 
    }   
}

例如:

 //===== Task.java =====
import java.util.TimerTask;

public class Task extends TimerTask ...{

    private String id;
    
    public Task(String id)...{
        this.id = id;
    }
    
    @Override
    public void run() ...{
        System.out.println(id+" is running...");
        
    }

}


//===== Test .java =====

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Test ...{

    /** *//**
     * @param args
     */
    public static void main(String[] args) ...{
        Timer timer = new Timer();
        TimerTask t1 = new Task("t1");
        TimerTask t2 = new Task("t2");
        //1000毫秒後,每隔1000毫秒執行一次t1任務
        timer.schedule(t1,1000,1000);
        //從現在開始,每隔500毫秒執行一次t2任務
        timer.schedule(t2, new Date(),500);
    
        
        try ...{
            Thread.sleep(10000);
        } catch (InterruptedException e) ...{
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        timer.cancel();
        System.out.println("---end---");

    }

}

在Spring定義 
<bean id="reportTimerTask" class="EmailReportTask">...</bean> 
配置定時器 
<bean id="scheduleReportTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> 
<property name="timerTask" ref="reportTimerTask" /> 
<property name="period"> 
<value>86400000</value> 
</property> 
</bean> 
timerTask屬性告訴ScheduledTimerTask執行哪個。86400000代表24個小時 
啟動定時器 
Spring的TimerFactoryBean負責啟動定時任務 
<bean class="org.springframework.scheduling.timer.TimerFactoryBean"> 
<property name="scheduledTimerTasks"> 
   <list><ref bean="scheduleReportTask"/></list> 
</property> 
</bean> 
scheduledTimerTasks裡顯示一個需要啟動的定時器任務的列表。 
可以通過設定delay屬性延遲啟動 
<bean id="scheduleReportTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> 
<property name="timerTask" ref="reportTimerTask" /> 
<property name="period"> 
<value>86400000</value> 
</property> 
<property name="delay"> 
<value>3600000</value> 
</property> 
</bean> 
這個任務我們只能規定每隔24小時執行一次,無法精確到某時啟動 
2.Quartz定時器 
首先繼承QuartzJobBean類實現executeInternal方法 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 
import org.springframework.scheduling.quartz.QuartzJobBean;

public class EmailReportJob extends QuartzJobBean{ 
protected void executeInternal(JobExecutionContext arg0) 
throws JobExecutionException { 
... 


在Spring中定義 
<bean id="reportJob" class="org.springframework.scheduling.quartz.JobDetailBean"> 
<property name="jobClass"> 
<value>EmailReportJob</value> 
</property> 
<property name="jobDataAsMap"> 
    <map> 
        <entry key="courseService"> 
            <ref bean="courseService"/> 
            </entry> 
    </map> 
</property> 
</bean> 
在這裡我們並沒有直接宣告一個EmailReportJob Bean,而是聲明瞭一個JobDetailBean。這個是Quartz的特點。JobDetailBean是Quartz的org.quartz.JobDetail的子類,它要求通過jobClass屬性來設定一個Job物件。 
使用Quartz的JobDetail中的另一個特別之處是EmailReportJob的courseService屬性是間接設定的。JobDetail的jobDataAsMap屬性接受一個Map,包括設定給jobClass的各種屬性,當。JobDetailBean例項化時,它會將courseService Bean注入到EmailReportJob 的courseService 屬性中。 
啟動定時器 
Quartz的org.quartz.Trigger類描述了何時及以怎樣的頻度執行一個Quartz工作。Spring提供了兩個觸發器SimpleTriggerBean和CronTriggerBean。 
SimpleTriggerBean與scheduledTimerTasks類似。指定工作的執行頻度,模仿scheduledTimerTasks配置
<bean id="simpleReportTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> 
<property name="jobDetail" ref="reprotJob" /> 
<property name="startDelay"> 
<value>360000</value> 
</property> 
<property name="repeatInterval"> 
    <value>86400000</value> 
</property> 
</bean> 
startDelay也是延遲1個小時啟動 
CronTriggerBean指定工作的準確執行時間 
<bean id="cronReportTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> 
<property name="jobDetail" ref="reprotJob" /> 
<property name="cronExpression"> 
<value>0 0 6 * * ?</value> 
</property> 
</bean> 
屬性cronExpression告訴何時觸發。最神祕就是cron表示式: 
Linux系統的計劃任務通常有cron來承擔。一個cron表示式有至少6個(也可能7個)有空格分隔的時間元素。從左到右: 
1.秒2.分3.小時4.月份中的日期(1-31)5.月份(1-12或JAN-DEC)6.星期中的日期(1-7或SUN-SAT)7.年份(1970-2099) 
每個元素都顯示的規定一個值(如6),一個區間(9-12),一個列表(9,11,13)或一個萬用字元(*)。因為4和6這兩個元素是互斥的,因此應該通過設定一個問號(?)來表明不想設定的那個欄位,“/”如果值組合就表示重複次數(10/6表示每10秒重複6次)。 
啟動定時器 
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
    <property name="triggers"> 
       <list><ref bean="cronReportTrigger"/></list> 
    </property> 
</bean> 
triggers屬性接受一組觸發器。

---------------------------------------------

cron表示式(quartz中時間表達式)
Quartz使用類似於Linux下的Cron表示式定義時間規則,Cron表示式由6或7個由空格分隔的時間欄位組成,如表1所示:

表1 Cron表示式時間欄位

Cron表示式的時間欄位除允許設定數值外,還可使用一些特殊的字元,提供列表、範圍、萬用字元等功能,細說如下:

●星號(*):可用在所有欄位中,表示對應時間域的每一個時刻,例如,*在分鐘欄位時,表示“每分鐘”;

●問號(?):該字元只在日期和星期欄位中使用,它通常指定為“無意義的值”,相當於點位符;

●減號(-):表達一個範圍,如在小時欄位中使用“10-12”,則表示從10到12點,即10,11,12;

●逗號(,):表達一個列表值,如在星期欄位中使用“MON,WED,FRI”,則表示星期一,星期三和星期五;

●斜槓(/):x/y表達一個等步長序列,x為起始值,y為增量步長值。如在分鐘欄位中使用0/15,則表示為0,15,30和45秒,而5/15在分鐘欄位中表示5,20,35,50,你也可以使用*/y,它等同於0/y;

●L:該字元只在日期和星期欄位中使用,代表“Last”的意思,但它在兩個欄位中意思不同。L在日期欄位中,表示這個月份的最後一天,如一月的31號,非閏年二月的28號;如果L用在星期中,則表示星期六,等同於7。但是,如果L出現在星期欄位裡,而且在前面有一個數值X,則表示“這個月的最後X天”,例如,6L表示該月的最後星期五;

●W:該字元只能出現在日期欄位裡,是對前導日期的修飾,表示離該日期最近的工作日。例如15W表示離該月15號最近的工作日,如果該月15號是星期六,則匹配14號星期五;如果15日是星期日,則匹配16號星期一;如果15號是星期二,那結果就是15號星期二。但必須注意關聯的匹配日期不能夠跨月,如你指定1W,如果1號是星期六,結果匹配的是3號星期一,而非上個月最後的那天。W字串只能指定單一日期,而不能指定日期範圍;

●LW組合:在日期欄位可以組合使用LW,它的意思是當月的最後一個工作日;

●井號(#):該字元只能在星期欄位中使用,表示當月某個工作日。如6#3表示當月的第三個星期五(6表示星期五,#3表示當前的第三個),而4#5表示當月的第五個星期三,假設當月沒有第五個星期三,忽略不觸發;

● C:該字元只在日期和星期欄位中使用,代表“Calendar”的意思。它的意思是計劃所關聯的日期,如果日期沒有被關聯,則相當於日曆中所有日期。例如5C在日期欄位中就相當於日曆5日以後的第一天。1C在星期欄位中相當於星期日後的第一天。

Cron表示式對特殊字元的大小寫不敏感,對代表星期的縮寫英文大小寫也不敏感。

表2下面給出一些完整的Cron表示式的例項: