昨天看定时器,被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包要完整哦!其实定时器还是挺简单的对不对。