標籤:
Quartz在Java構建的系統中,是十分常用的定時任務架構。
本文,記錄、介紹Quartz的簡單入門的單獨搭建(此文入門學習Quartz為主,並非基於Spring託管形式)。
> 參考的優秀資料
Quartz Quick Start Guide
Chapter 3: Logback configuration
> 版本說明
除了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 = MySchedulerorg.quartz.threadPool.threadCount = 3org.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(圖二)。
圖一
圖二
【Quartz】Quartz的簡單搭建