【Quartz】Quartz的搭建、應用(單獨使用Quartz)


Quartz在Java構建的系統中,是十分常用的定時任務框架。

本文記錄和介紹Quartz的簡單入門的單獨搭建。

注:本文以入門學習Quartz為主,並非基於Spring托管形式。其中有另一篇關於Spring Boot與Quartz集成的博文《Quartz與Spring Boot集成使用》。

 

版本說明

除了Quartz,還引入logback(為了看詳細的日志嘛!)

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

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.0</version>
        </dependency>
    </dependencies>
View Code

 

簡單的搭建

jar包的引入參考上述的pom文件。

 

quartz.properties,配置quartz的設置。

,org.quartz.threadPool.threadCount,配置線程池的容量,即表示同時最多可運行的線程數量。在生產環境,此參數應根據實際情況配置。

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
View Code

 

logback.xml,日志框架logback的配置。這里只簡單地配置了控制台和日志文件的輸出哦(>_<)

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder 
            by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>D:/logs/quartz_task_application.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>

</configuration>
View Code

 

HelloJob.java,具體執行的任務

package No01簡單的定時任務;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloJob implements Job {
    
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        // 此任務僅打印日志便於調試、觀察
        this.logger.debug(this.getClass().getName() + " trigger...");
    }

}
View Code

 

那么,在哪里定義“在什么時候執行什么任務呢?”

package No01簡單的定時任務;

import java.util.concurrent.TimeUnit;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Bootstrap {
    private static Logger logger = LoggerFactory.getLogger(Bootstrap.class);

    public static void main(String[] args) {

        try {
            // 獲取Scheduler實例
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();

            // 具體任務
            JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

            // 觸發時間點
            SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(5).repeatForever();
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                    .startNow().withSchedule(simpleScheduleBuilder).build();

            // 交由Scheduler安排觸發
            scheduler.scheduleJob(job, trigger);
            
            /* 為觀察程序運行,此設置主程序睡眠3分鍾才繼續往下運行(因下一個步驟是“關閉Scheduler”) */
            try {
                TimeUnit.MINUTES.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 關閉Scheduler
            scheduler.shutdown();

        } catch (SchedulerException se) {
            logger.error(se.getMessage(), se);
        }
    }

}
View Code

 

在Web應用中使用Quartz

Quartz也常用在Web應用中,常見的是交由Spring托管的形式,但這里並非介紹這個。這里介紹Quartz在Web應用中單獨使用。

 

一般來說,Web應用啟動時,應注冊已經確定的定時任務;一些動態的、未確定觸發時間的定時任務,后續可通過靜態的Scheduler注冊。

這里使用監聽器在應用啟動時注冊,記得在web.xml注冊這個監聽器哦(>_<);在關閉Web應用時,也要相應的注銷定時任務。

其他配置文件、Java類與上例子相同,這里只是注冊定時任務的地方換成此監聽器了。

package No02Web應用使用Quartz;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import No01簡單的定時任務.HelloJob;

/**
 * Application Lifecycle Listener implementation class AListener
 *
 */
public class ApplicationContextListener implements ServletContextListener {
    
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    public static Scheduler scheduler = null;

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        this.logger.info("The application start...");
        
        /* 注冊定時任務 */
        try {
            // 獲取Scheduler實例
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();

            // 具體任務
            JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

            // 觸發時間點
            SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(5).repeatForever();
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                    .startNow().withSchedule(simpleScheduleBuilder).build();

            // 交由Scheduler安排觸發
            scheduler.scheduleJob(job, trigger);
            
            this.logger.info("The scheduler register...");
        } catch (SchedulerException se) {
            logger.error(se.getMessage(), se);
        }
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        this.logger.info("The application stop...");
        
        /* 注銷定時任務 */
        try {
            // 關閉Scheduler
            scheduler.shutdown();
            
            this.logger.info("The scheduler shutdown...");
        } catch (SchedulerException se) {
            logger.error(se.getMessage(), se);
        }
    }

}
View Code

 

    <listener>
        <listener-class>No02Web應用使用Quartz.ApplicationContextListener</listener-class>
    </listener>
View Code

 

,如果你在Eclipse中調試,可能發現無法看到contextDestroyed方法的執行,請注意用Stop方式(圖一)關閉應用,而不是Terminate(圖二)。

圖一

 

圖二

 

常用的Cron Schedule

相對於其他方式定義定時任務的觸發時間,我們較常用Cron Schedule,小伙伴們也是吧?

 

Cron Schedule的使用

// 具體任務
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

// 觸發時間點
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 * * * * ? *");
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
        .withSchedule(cronScheduleBuilder).build();

// 交由Scheduler安排觸發
scheduler.scheduleJob(job, trigger);
View Code

 

而Cron Expression的學習可參考下列優秀的文章:

Tutorial - Lesson 6: CronTrigger

Spring - Quartz - cronExpression中問號(?)的解釋

參考的優秀資料

Quartz Quick Start Guide

Chapter 3: Logback configuration

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM