先说明一下,Java有自带的定时任务类Timer和TimerTask,可以实现简单的定时任务,但是对于复杂的任务处理支持的不是很好。这里就不做说明了,直接上今天所使用的第三方的定时自动任务的框架quartz,jar的版本是2.0.2;
注:如果是不需要动态设置时间的,可以直接和spring结合,通过配置文件的方式更简单。我们文中主要是对动态设置时间的定时自动任务做一下说明。
说一下,定时自动任务的三个要素:
1:自动任务的控制器,用于操作定时自动任务的的管理器;
2:定时自动任务的触发器,触发定时自动任务;
3:执行自动任务的job类了;
这里是定时任务管理类的代码:
public class SchedulerRun {
private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
/**
* 功能: 添加一个定时任务
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务的类类型 eg:TimedMassJob.class
* @param cron 时间设置 表达式,参考quartz说明文档
* @param objects 可变参数需要进行传参的值
*/
public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String cron,Object...objects) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
// 任务名,任务组,任务执行类
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
// 触发器
if(objects!=null){
for (int i = 0; i < objects.length; i++) {
//该数据可以通过Job中的JobDataMap dataMap = context.getJobDetail().getJobDataMap();来进行参数传递值
jobDetail.getJobDataMap().put("data"+(i+1), objects[i]);
}
}
TriggerBuilder
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName,triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 调度容器设置JobDetail和Trigger
scheduler.scheduleJob(jobDetail, trigger);
// 启动
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 功能:修改一个任务的触发时间
* @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 scheduler = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
// 触发器
TriggerBuilder
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一个任务的触发时间
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 功能: 移除一个任务
* @param jobName
* @param jobGroupName
* @param triggerName
* @param triggerGroupName
*/
public static void removeJob(String jobName, String jobGroupName,String triggerName, String triggerGroupName) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName);
// 停止触发器
scheduler.pauseTrigger(triggerKey);
// 移除触发器
scheduler.unscheduleJob(triggerKey);
// 删除任务
scheduler.deleteJob(JobKey.jobKey(jobName,jobGroupName));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
*
* 功能:启动所有定时任务
*/
public static void startJobs() {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 功能:关闭所有定时任务
*/
public static void shutdownJobs() {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
下面是在任务栈中添加一个自动任务
HtzckcJob job = new HtzckcJob();
SchedulerRun.addJob(job_name,jobGroupName,triggerName,triggerGroupName,job.getClass(),cronDateStr,null);
上面的参数cronDateStr是通过时间类转换得到的cron的表达式:
转换实现如下:
public class FormatDateToCron {
/***
* 功能描述:日期转换cron表达式
* @param date
* @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss
* @return
*/
public static String formatDateByPattern(Date date,String dateFormat){
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
String formatTimeStr = null;
if (date != null) {
formatTimeStr = sdf.format(date);
}
return formatTimeStr;
}
/**
* 功能描述:每天ss mm HH这个时间执行执行一次
* @param date
* @return
*/
public static String getCronDay(Date date){
String dateFormat="ss mm HH * * ?";
return formatDateByPattern(date, dateFormat);
}
/**
* 功能描述:每天ss mm HH这个时间执行执行一次
* @param date
* @return
*/
public static String getCronMonth(Date date){
String dateFormat="ss mm HH dd MM ?";
return formatDateByPattern(date, dateFormat);
}
/**
* 功能描述:每天ss mm HH这个时间执行执行一次
* @param date
* @return
*/
public static String getCronSecond(Date date){
String dateFormat="ss * * * * ?";
return formatDateByPattern(date, dateFormat);
}
}
自动任务执行的job,这里书写业务方法,
public class HtzckcJob implements Job{
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
//1: 执行时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println(sdf.format(new Date()));
}
}
主要的代码都有注释,底层的技术可以自行查看文档,大家有更好的方式可以一起交流一下!