昨天看定時器,被Quartz定時器框架困擾到現在,以爲是調用的時候出了問題,以爲是我不知道怎麼調用然後出的問題,結果是少了jar包。哎,這個問題真的是,告訴我們以後導入一個框架的jar包時,一定要導全,不要只導核心包,因爲核心包可能依賴其他包。
定時任務不執行原因:沒有導入除quartz-2.3.0-SHAPSHOT.jar以外的包。
解決方法,把其餘包都導入。
這個問題真的是!!!!!真是個值得記憶的教訓。現在來說說定時器吧!
我在理解定時器的時候,提出了這些問題!
首先,jdk自帶Timer,TimerTask類,可以實現定時任務,爲什麼還需要其他定時器框架呢?
用java自帶的類來做定時任務時,只需寫一個類,讓這個類extendsTimerTask,然後重寫它的Run()方法。
然後,如果把定時器放在監聽器裏的話,直接在監聽器的某個方法中執行Timer的schedule(task,...)方法。
我們可以發現,
schedule(task, 0, PERIOD*PERIODTIME);方法實現的定時種類不多。它不能控制一些複雜的定時任務。
所以這就是爲什麼要使用其他定時器框架的原因吧,因爲不能滿足複雜的任務需求。
那常見的定時器框架有哪些呢?
java定時器,Spring定時器,Quartz定時器。
我暫時只用過java自帶的定時器和Quartz定時器,因爲Quartz定時器已經夠強大了,我覺得了解Spring定時器也就沒必要了。
那Quartz定時器框架是怎麼用的呢?
首先我們要理解Quartz的幾個核心概念。
然後我們要引入我們需要的jar包,注意一個都不能少,不然會引發一系列問題,前面已經截圖過。
最後我們進入代碼部分。
我們要先建一個job類,它是任務的核心,即這個定時任務究竟要做什麼,就是做的內容。這個類需要implements該框架的Job類,然後實現它的execute()方法,方法的具體內容就是執行的這個任務,即任務的內容。
然後,我們需要創建一個JobDetail。
JobDetail 表示一個具體的可執行的調度程序,Job 是這個可執行程調度程序所要執行的內容,另外 JobDetail 還包含了這個任務調度的方案和策略。最開始創建的job類就會在創建它時被用到。
接着呢,我們需要創建一個觸發器,Trigger 。
Trigger 代表一個調度參數的配置,什麼時候去調。它可以配置定時任務中的定時。尤其是cron表達式的配置,讓定時任務想怎麼定時就怎麼定時,配置可以在http://cron.qqe2.com/中生成,方便快捷。
最後呢,我們需要一個調度器,Scheduler。
Scheduler 代表一個調度容器,一個調度容器中可以註冊多個 JobDetail 和 Trigger。當 Trigger 與 JobDetail 組合,就可以被 Scheduler 容器調度了。剛剛創建的JobDetail和Trigger都需被它調度。
最後的最後,我們只需在監聽器或者其他地方直接調用剛剛寫好的方法即可,然後如果實在監聽器裏調用的話,程序一執行,定時任務就開始了。下面我粘一下我的代碼。
web.xml中的配置。
<listener>
<listener-class>com.practice.mylistener.QuartzListener</listener-class>
</listener>
QuartzListener類。
package com.practice.mylistener;
import com.practice.tool.QuartzTimeManager;
import com.practice.tool.QuertzTask;
import com.practice.tool.job;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class QuartzListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("quertztask監聽器啓動==============================");
QuartzTimeManager.addJob("myJob","group1","mytrigger","group1", job.class,"1-2 * * * * ?");
System.out.println("task excute==================================");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
QuartzListener類
package com.practice.tool;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Collection;
public class QuartzTimeManager {
private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
/**
* @Description: 添加一個定時任務
*
* @param jobName 任務名
* @param jobGroupName 任務組名
* @param triggerName 觸發器名
* @param triggerGroupName 觸發器組名
* @param jobClass 任務
* @param cron 時間設置,參考quartz說明文檔
*/
public static void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class jobClass, String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
// 任務名,任務組,任務執行類
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
// 觸發器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發器名,觸發器組
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 觸發器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 創建Trigger對象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 調度容器設置JobDetail和Trigger
sched.scheduleJob(jobDetail, trigger);
// 啓動
if (!sched.isShutdown()) {
System.out.println("=================定quartz定時任務開始");
sched.start();
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 修改一個任務的觸發時間
*
* @param jobName
* @param jobGroupName
* @param triggerName 觸發器名
* @param triggerGroupName 觸發器組名
* @param cron 時間設置,參考quartz說明文檔
*/
public static void modifyJobTime(String jobName,
String jobGroupName, String triggerName, String triggerGroupName, String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
/** 方式一 :調用 rescheduleJob 開始 */
// 觸發器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發器名,觸發器組
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 觸發器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 創建Trigger對象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一個任務的觸發時間
sched.rescheduleJob(triggerKey, trigger);
/** 方式一 :調用 rescheduleJob 結束 */
/** 方式二:先刪除,然後在創建一個新的Job */
//JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
//Class<? extends Job> jobClass = jobDetail.getJobClass();
//removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
//addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
/** 方式二 :先刪除,然後在創建一個新的Job */
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一個任務
*
* @param jobName
* @param jobGroupName
* @param triggerName
* @param triggerGroupName
*/
public static void removeJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
sched.pauseTrigger(triggerKey);// 停止觸發器
sched.unscheduleJob(triggerKey);// 移除觸發器
sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 刪除任務
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:啓動所有定時任務
*/
public static void startJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:關閉所有定時任務
*/
public static void shutdownJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
job類
package com.practice.tool;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class job implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext)
throws JobExecutionException {
System.out.println("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
Date date=new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Time:"+sf.format(date));
System.out.println("Hello");
}
}
運行結果:
最重要的一點,注意導入jar包要完整哦!其實定時器還是挺簡單的對不對。