定時器(Quartz)快速入門

摘要: Quartz是一個任務日程管理系統,這個系統能夠與任何其餘軟件系統集成或者一塊兒使用。術語「日程進度管理器」可能對於不一樣的人有不一樣的理解。當你閱讀這個指南以後, 你會對這個術語有固定的理解。簡而言之,「任務進度管理器」就是一個在預先肯定(被歸入日程)的時間到達時,負責執行(或者通知)其餘軟件組件的系統。java

Quartz概述

Quartz中的觸發器web

Quartz中提供了兩種觸發器,分別是CronTrigger和SimpleTrigger。spring

SimpleTriggerapache

每 隔若干毫秒來觸發歸入進度的任務。所以,對於夏令時來講,根本不須要作任何特殊的處理來「保持進度」。它只是簡單地保持每隔若干毫秒來觸發一次,不管你的 SimpleTrigger每隔10秒觸發一次仍是每隔15分鐘觸發一次,仍是每隔24小時觸發一次。編程

CronTriggerapi

在特定「格林日曆」時刻觸發歸入進程的任務,所以,若是建立一個在天天上午10點觸發的觸發器,那麼,在夏令時執行以前,系統將繼續如此運做。可是,取決因而 春季仍是秋季夏令時,由於對於特定的星期日,從星期六上午10點到星期日上午10點之間的時間間隔將不是24小時,而多是23或者25個小時。tomcat

總之,若是你記住下面的兩條規則,則會感受良好而且很容易記憶:
• SimpleTrigger 老是每隔若干秒觸發,而同夏令時沒有關係。
• CronTrigger 老是在給定的時間出發而後計算它下次觸發的時間。若是在給定的日期內沒有該時間,則觸發器將會被忽略,若是在給定的日期內該時間發生了兩次,它只觸發一次。由於是在第一次觸發發生後計算當天下次觸發的時間。併發

快速開始

構建app

能夠在http://sourceforge.net/projects/quartz/連接中下載Quartz包,也能夠經過Maven來進行構建,若是讀者以爲麻煩,能夠採用下載jar包的方法,由於Quartz依賴於其它包。我這裏經過Maven來進行構建:框架

首先構建公共依賴項,用於公共模塊使用:

<properties>
    <!--Spring版本號-->
    <spring.version>3.2.4.RELEASE</spring.version>
    <!--log4j日誌文件管理包版本-->
    <slf4j.version>1.6.6</slf4j.version>
    <log4j.version>1.2.12</log4j.version>
</properties>

<dependencies>

    <!--Junit測試包-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
    </dependency>

    <!--日誌文件管理包-->
    <!--log start-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <!--log end-->

    <!--Apache 組件-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.3</version>
    </dependency>

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>

    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>

</dependencies>

 

下面添加Quartz依賴項:

<dependencies>

    <!--添加Quartz框架-->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.1.1</version>
    </dependency>

    <!--組件可選項-->
    <!--start-->
    <dependency>
        <groupId>javax.transaction</groupId>
        <artifactId>jta</artifactId>
        <version>1.1</version>
    </dependency>

    <dependency>
        <groupId>commons-digester</groupId>
        <artifactId>commons-digester</artifactId>
        <version>1.8</version>
    </dependency>

    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!--end-->

</dependencies>

在公共模塊記得要將模塊打包方式設置爲pom。

我這裏的Quartz爲較新的2.1.x版本,由於在與Spring整合時,Spring3.1.0以前的版本只支持Quartz1.6以往的版本。

至於log4j如何配置,這裏就不在贅言了,讀者能夠參考網上自行搜索。

單一Job調度

建立一個Quartz Job類

每個 Quartz Job 必須有一個實現了org.quartz.Job接口的具體類。這個接口僅有一個要你在 Job 中實現的方法,execute(),方法execute()的原型以下:
public void execute(JobExecutionContext context) throws JobExecutionException;

當 Quartz 調度器肯定到時間要激發一個 Job 的時候,它就會生成一個 Job 實例,並調用這個實例的execute()方法。調度器只管調用execute()方法,而不關心執行的結果,除了在做業執行中出問題拋出的 org.quartz.JobExecutionException異常。

下面是咱們的第一個 Quartz job,它被設計來掃描一個目錄中的文並顯示文件的詳細信息。

import ***;

/**
 * 定義一個Job掃描一個目錄中的文件,並顯示文件的詳細信息
 *
 * @author Barudisshu
 */
public class ScanDirectoryJob implements Job {

    private static Logger logger = Logger.getLogger(ScanDirectoryJob.class);

    /**
     * Job接口中的execute方法體內爲一個邏輯事務,全部工做事務在這裏完成
     *
     * @param context 執行上下文環境,
     * 包含jobDetail、trigger、jobDataMap、calendar等一系列組合子項
     * @throws JobExecutionException
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

        // Every job has its own job detail
        JobDetail jobDetail = context.getJobDetail();

        // The name is defined in the job definition
        String jobName = ((JobDetailImpl)jobDetail).getName();   //任務名稱

        // Log the time the job started
        logger.info(jobName + " fired at " + new Date());   //記錄任務開始的時間

        // The directory to scan is stored in the job map
        JobDataMap dataMap = jobDetail.getJobDataMap();     //任務所配置的數據映射表

        String dirName = dataMap.getString("SCAN_DIR");     //獲取要掃描的目錄

        // Validate the required input
        if (dirName == null) {//所須要的掃描目錄沒有提供
            throw new JobExecutionException("Directory not configured");
        }

        // Make sure the directory exists
        File dir = new File(dirName);
        if (!dir.exists()) {//提供的是錯誤目錄
            throw new JobExecutionException("Invalid Dir " + dirName);
        }

        // Use FileFilter to get only XML files
        FileFilter filter = new FileExtensionFileFilter(".xml");
        // 只統計XML文件
        File[] files = dir.listFiles(filter);

        if (files == null || files.length <= 0) {//目錄下沒有XML文件
            logger.info("No XML files found in " + dir);

            // Return since there were no files
            return;
        }

        // The number of XML files
        int size = files.length;
        logger.info("The number of XML files: " + size);

        // Iterate through the files found
        for (File file : files) {
            // Log something interesting about each file
            File aFile = file.getAbsoluteFile();
            long fileSize = file.length();
            String msg = aFile + " - Size: " + fileSize;

            logger.info(msg);   //記錄下文件的路徑和大小
        }
    }
}

當 Quartz 調用 execute() 方法,會傳遞一個 org.quartz.JobExecutionContext 上下文變量,裏面封裝有 Quartz 的運行時環境和當前正執行的 Job。經過 JobexecutionContext,你能夠訪問到調度器的信息,做業和做業上的觸發器的信息,還有更多更多的信息。在代碼 中,JobExecutionContext 被用來訪問 org.quartz.JobDetail 類,JobDetail 類持有 Job 的詳細信息,包括爲 Job 實例指定的名稱,Job 所屬組,Job 是否被持久化(易失性),和許多其餘感興趣的屬性。

JobDetail 又持有一個指向 org.quartz.JobDataMap 的引用。JobDataMap 中有爲指定 Job 配置的自定義屬性。例如,在代碼中咱們從 JobDataMap 中得到欲掃描的目錄名,咱們能夠在 ScanDirectoryJob 中硬編碼這個目錄名,可是這樣的話咱們難以重用這個 Job 來掃描別的目錄了。在後面你將會看到目錄是如何配置到 JobDataMap 的。
execute() 方法中剩下的就是標準 Java 代碼了:得到目錄名並建立一個 java.io.File 對象。它還對目錄名做爲簡單的校驗,確保是一個有效且存在的目錄。接着調用 File 對象的 listFiles() 方法獲得目錄下的文件。還建立了一個 java.io.FileFilter 對象做爲參數傳遞給 listFiles() 方法。org.quartzbook.cavaness.FileExtensionFileFilter 實現了 java.io.FileFilter 接口,它的做用是過濾掉目錄僅返回 XML 文件。默認狀況下,listFiles() 方法是返回目錄中全部內容,不論是文件仍是子目錄,因此咱們必須過濾一下,由於咱們只對 XML 文件感興趣。
FileExtensionFileFilter 被用來屏蔽名稱中不含字符串 「.xml」 的文件。它還屏蔽了子目錄--這些子目錄本來會讓 listFiles() 方法正常返回。過濾器提供了一種很便利的方式選擇性的向你的 Quartz 做業提供它能接受的做爲輸入的文件。

import ***;

/**
 * @author Barudisshu
 */
public class FileExtensionFileFilter implements FileFilter {

    private String extension;   //文件後綴

    public FileExtensionFileFilter(String extension) {
        this.extension = extension;
    }

    @Override
    public boolean accept(File pathname) {//只接受指定後綴的文件

        //若是file是個目錄
        if(pathname.isDirectory()) return false;

        // Lowercase the filename for easier comparison
        String LCaseFilename = pathname.getName().toLowerCase();    //文件名轉換爲小寫

        return (pathname.isFile() && (LCaseFilename.indexOf(extension) > 0));
    }
}

到 目前爲止,咱們已經建立了一個 Quartz job,但尚未決定怎麼處置它--明顯地,咱們需以某種方式爲這個 Job 設置一個運行時間表。時間表能夠是一次性的事件,或者咱們可能會安裝它在除週日以外的每一個午夜執行。你即刻將會看到,Quartz Schduler 是框架的心臟與靈魂。全部的 Job 都經過 Schduler 註冊;必要時,Scheduler 也會建立 Job 類的實例,並執行實例的 execute() 方法。

單元測試

Quartz2.x以上版本和以往版本有許多的不一樣,主要是JobDetail和Trigger不在經過實例構建,而是由構造器進行構建,經過減小實例的構建來優化內存處理,這樣對效率有很大的提升。
Quartz 提供了四種類型的 Trigger,但其中兩種是最爲經常使用的,它們就是上面提到的 SimpleTrigger 和 CronTrigger。CronTrigger用法比SimpleTrigger稍微複雜一點,可是用法都同樣,所以這裏不作介紹,能夠參考 CronTrigger表達式相關內容。

import ***;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

/**
 * @author Barudisshu
 */
public class SimpleSchedulerTests {

    private static Logger logger = Logger.getLogger(SimpleSchedulerTests.class);

    private Scheduler createScheduler() throws SchedulerException {//建立調度器
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        return schedulerFactory.getScheduler();
    }

    private void scheduleJob(Scheduler scheduler) throws SchedulerException {
        // Create a job detail for the job
        JobDetail jobDetail = newJob(ScanDirectoryJob.class)
                .withIdentity("ScanDirectory", "jobDetail-group")
                .withDescription("ScanDirectory from tomcat conf")
                .build();

        // Configure the directory to scan
        jobDetail.getJobDataMap()
                .put("SCAN_DIR", "\apache-tomcat-7.0.39\conf");

        // Create a trigger that fires every 10 seconds,forever
        Trigger trigger = newTrigger()
                .withIdentity("scanTrigger", "trigger-group")
                .startNow()
                .withSchedule(simpleSchedule()
                        .withIntervalInSeconds(10)) // 每十秒觸發一次
                .build();

        //Associate the trigger with the job in the schedule
        scheduler.scheduleJob(jobDetail, trigger);

    }

    @Test
    public void ScanDirectoryTests() {
        SimpleSchedulerTests simpleSchedulerTests = new SimpleSchedulerTests();
        try {
            Scheduler scheduler = simpleSchedulerTests.createScheduler();

            // Start the scheduler running
            scheduler.start();

            logger.info("Scheduler started at " + new Date());
            simpleSchedulerTests.scheduleJob(scheduler);

            // Stop the scheduler after 10 second
            Thread.sleep(10000);
            scheduler.shutdown();
        } catch (SchedulerException e) {
            logger.error(e);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

多個Job調度

Quartz容許多個Job調度,Job做業是創建在Schedule上的,這和Quartz1.6.x以前的版本的概念稍微有點不一樣,不過不用在乎這些概念上細節。下面經過單元測試來講明如何進行多個Job調度。

import ***;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

/**
 * @author Barudisshu
 */
public class MultiJobSchedulerTests {

    private static Logger logger = Logger.getLogger(MultiJobSchedulerTests.class);

    private Scheduler createScheduler() throws SchedulerException {//建立調度器
        return new StdSchedulerFactory().getScheduler();
    }

    private void scheduleJob(Scheduler scheduler, String jobName,
        Class<? extends Job> jobClass, String scanDir,
        String triggerName, int scanInterval) throws SchedulerException {
        // Create a job detail for the job
        JobDetail jobDetail = newJob(jobClass)
                .withIdentity(jobName, "jobDetail-group")
                .build();

        // Configure the directory to scan
        jobDetail.getJobDataMap()
                .put("SCAN_DIR", scanDir);

        // Create a trigger that fires every 10 seconds,forever
        Trigger trigger = newTrigger()
                .withIdentity(triggerName, "trigger-group")
                .startNow()
                .withSchedule(simpleSchedule()
                        .withIntervalInSeconds(scanInterval)) // 每十秒觸發一次
                .build();

        //Associate the trigger with the job in the schedule
        scheduler.scheduleJob(jobDetail, trigger);

    }

    @Test
    public void multiScanTests() {

        MultiJobSchedulerTests multiJobSchedulerTests =
            new MultiJobSchedulerTests();

        try {
            Scheduler scheduler = multiJobSchedulerTests.createScheduler();

            // Scheduler the first job
            multiJobSchedulerTests.scheduleJob(scheduler,
                 "ScanTomcat", ScanDirectoryJob.class,
                 "\apache-tomcat-7.0.39\conf", "tomcatTrigger", 10);

            // Scheduler the second job
            multiJobSchedulerTests.scheduleJob(scheduler,
                 "ScanGlassfish", ScanDirectoryJob.class,
                 "\glassfish4\glassfish\domains\domain1\config",
                 "glassfishTrigger", 15);

            // Start the scheduler running
            scheduler.start();

            logger.info("Scheduler started at " + new Date());

            // Stop the scheduler after 10 second
            Thread.sleep(10000);
            scheduler.shutdown();
        } catch (SchedulerException e) {
            logger.error(e);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

加載XML文件實現Job調度

文 件 quartz.properties 定義了 Quartz 應用運行時行爲,還包含了許多能控制 Quartz 運轉的屬性。這個文件應該放在classpath所指的路徑下,好比咱們這個java工程,就將它和下面將介紹的jobs.xml一塊兒放在項目根目錄下就 是。若是不清楚就查看.classpath文件,它裏面就配置了你的項目的classpath。

構建本身quartz.properties

可 以經過自定quartz.properties來進行Job調度,須要注意的是,在實際項目中不要以quartz.properties同名進行命名,因 爲StdSchedulerFactory默認加載quartz.properties文件,所以我這裏命名爲scan- quartz.properties,配置以下:

# 固定前綴org.quartz
# 主要分爲scheduler、threadPool、jobStore、plugin等部分
#
#
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

# 實例化ThreadPool時,使用的線程類爲SimpleThreadPool
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

# threadCount和threadPriority將以setter的形式注入ThreadPool實例
# 併發個數
org.quartz.threadPool.threadCount = 5
# 優先級
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000

# 默認存儲在內存中
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

# 經過插件獲取聲明Job
org.quartz.plugin.jobInitializer.class =
    org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

插件配置

在這個簡單的 quartz.properties 文件中最後一部分是你要用到的 Quart 插件的配置。插件經常在別的開源框架上使用到,好比 Apache 的 Struts 框架(見 http://struts.apache.org/)。
一個聲明式擴框架的方法就是經過新加實現了 org.quartz.spi.SchedulerPlugin 接口的類。SchedulerPlugin 接口中有給調度器調用的三個方法。
要在咱們的例子中聲明式配置調度器信息,咱們會用到一個 Quartz 自帶的叫作 org.quartz.plugins.xml.JobInitializationPlugin 的插件。
默認時,這個插件會在 classpath 中搜索名爲 quartz_jobs.xml 的文件並從中加載 Job 和 Trigger 信息。

XML配置

下面就是目錄掃描例子的 Job 定義的 XML 文件。正如上一篇所示例子那樣,這裏咱們用的是聲明式途徑來配置 Job 和 Trigger 信息的:

<?xml version='1.0' encoding='utf-8'?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="
                     http://www.quartz-scheduler.org/xml/JobSchedulingData
                     http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
                     version="1.8">

    <schedule>
        <job>
            <name>ScanDirectory</name>
            <group>jobDetail-group</group>

            <description>ScanDirectory from tomcat conf</description>
            <job-class>net.individuals.quartz.ScanDirectoryJob</job-class>
            <job-data-map>
                <entry>
                    <key>SCAN_DIR</key>
                    <value>\apache-tomcat-7.0.39\conf</value>
                </entry>
            </job-data-map>
        </job>

        <trigger>
            <simple>
                <name>scanTrigger</name>
                <group>trigger-group</group>

                <!--jobName和jobGroup必須與對應的Job匹配-->
                <job-name>ScanDirectory</job-name>
                <job-group>jobDetail-group</job-group>

                <!--注意日期和時間-->
                <start-time>2008-09-03T14:43:00</start-time>
                <!-- repeat indefinitely every 10 seconds -->
                <repeat-count>-1</repeat-count>
                <repeat-interval>10000</repeat-interval>
            </simple>
        </trigger>
    </schedule>
</job-scheduling-data>

在jobs.xml 中 的格式是:

<start-time>2008-09-03T14:43:00</start-time>

其中T隔開日期和時間,默認時區

或者:

<start-time>2008-09-03T14:43:00+08:00</start-time>

其中+08:00 表示東八區

元素描述了一個要註冊到調度器上的 Job,至關於咱們在前面章節中使用 scheduleJob() 方法那樣。你所看到的 和 這兩個元素就是咱們在代碼中以編程式傳遞給方法 schedulerJob() 的參數。
這裏的XML配置和Quartz1.6.x也有許多不一樣,但實質都是同樣,不用在乎這些細節。

XML配置單元測試

下面進行上述描述文件的加載和測試:

import ***;

/**
 * @author Barudisshu
 */
public class LoadXmlTests {

    private static Logger logger = Logger.getLogger(LoadXmlTests.class);

    private Scheduler createScheduler() throws SchedulerException {//建立調度器
        return new StdSchedulerFactory("scan-quartz.properties").getScheduler();
    }

    @Test
    public void ScanDirectoryTests() {
        LoadXmlTests loadXmlTests = new LoadXmlTests();
        try {
            Scheduler scheduler = loadXmlTests.createScheduler();

            // Start the scheduler running
            scheduler.start();

            logger.info("Scheduler started at " + new Date());

            // Stop the scheduler after 10 second
            Thread.sleep(20000);
            scheduler.shutdown();
        } catch (SchedulerException e) {
            logger.error(e);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

怎樣?是否是以爲簡單了不少(我就不明白爲何有些人反對XML配置,XML配置不是挺好的嗎?一目瞭然)

Quartz的Web構建

Quartz的Web構建依賴項須要將打包方式改成war便可,下面以一個簡單的HelloWorld爲例進行說明:

import ***;

/**
 * @author Barudisshu
 */
public class HelloWorld implements Job {

    private static Logger logger = Logger.getLogger(HelloWorld.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        logger.info("\n---------------------------------" +
                "\n\nHello World! \n\n" +
                "---------------------------------\n" +
                new Date());
    }
}

WEB構建基本上依賴配置文件,咱們只須要的web工程的web.xml中配置相應項便可:

<!--quartz配置1:-->
<context-param>
    <param-name>quartz:config-file</param-name>
    <param-value>web-quartz.properties</param-value>
</context-param>
<context-param>
    <param-name>quartz:shutdown-on-unload</param-name>
    <param-value>true</param-value>
</context-param>
<context-param>
    <param-name>quartz:wait-on-shutdown</param-name>
    <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>quartz:start-scheduler-on-load</param-name>
    <param-value>true</param-value>
</context-param>
<listener>
    <listener-class>
        org.quartz.ee.servlet.QuartzInitializerListener
    </listener-class>
</listener>

<!--quartz配置2:-->
<servlet>
    <servlet-name>QuartzInitializer</servlet-name>
    <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
    <init-param>
        <param-name>shutdown-on-unload</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>QuartzInitializer</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

這樣,在啓動Tomcat的時候,QuartzInitializerServlet這個Servlet就會自動讀取quartz.properties這個配置文件,並初始化調度信息,啓動Scheduler。

和Spring集成

Spring 的scheduling.quartz包中對Quartz框架進行了封裝,使得開發時不用寫任何QuartSpring的代碼就能夠實現定時任務。 Spring經過JobDetailBean,MethodInvokingJobDetailFactoryBean實現Job的定義。後者更加實用, 只需指定要運行的類,和該類中要運行的方法便可,Spring將自動生成符合Quartz要求的JobDetail。

構建依賴項

<!--添加Spring框架-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
</dependency>

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.1.1</version>
</dependency>

建立任務類

這裏的任務類不須要實現Job接口,而且注意任務的方法不能帶參數,不然Spring會報錯找不到該方法:

import ***;

/**
 * @author Barudisshu
 */
public class HelloWorld{

    private static Logger logger = Logger.getLogger(HelloWorld.class);

    public HelloWorld() {
    }

    /**
     * spring 檢測要求不帶參數
     */
    public void execute() {
        logger.info("-----------------------------------------" +
                "\n\nKick your ass and fuck your mother! \n\n" +
                "-----------------------------------------" +
                new Date());
    }
}

Spring的applicationContext.xml配置文件修改以下:

<!--要調用的工做類-->
<bean id="quartzJob" class="net.individuals.quartz.HelloWorld"/>

<!--定義調用對象和調用對象的方法-->
<bean id="jobtask"
    class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <!--調用類-->
    <property name="targetObject" ref="quartzJob"/>
    <!--調用方法-->
    <property name="targetMethod" value="execute"/>

</bean>
<!--定義觸發時間-->
<bean id="doTime"
    class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="jobtask"/>
    <!--cron表達式-->
    <property name="cronExpression" value="0/5 * * * * ?"/>
</bean>
<!--總管理類-->
<bean id="startQuartz"
    lazy-init="false"
    autowire="no"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <!--任務列表-->
        <list>
            <ref bean="doTime"/>
        </list>
    </property>
</bean>

這裏Bean的注入方式因我的喜愛,也能夠自動注入,另外web.xml的配置這裏也不在贅言,請自行Spring文檔。

注意,若是運行期間出錯,多是Spring的版本或者某些包衝突,我這裏的Spring版本爲3.2.四、Quartz爲2.1.1 。

相關文章
相關標籤/搜索