文章目录
相关依赖
<!-- 定时任务 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
相关工具类
一、类的转换
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 类转换器
*/
public class ClassUtil {
@SuppressWarnings("unchecked")
public static Class<? extends QuartzJobBean> getClass(String classname) throws Exception {
Class<?> class1 = Class.forName(classname);
return (Class<? extends QuartzJobBean>) class1;
}
}
二、cron表达式生成工具类
import java.text.SimpleDateFormat;
import java.util.Date;
public class CronUtil {
/**
* 生成指定格式日期字符
*
* @param date 日期
* @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss
* @return formatTimeStr
*/
public static String formatDateByPattern(Date date, String dateFormat) {
dateFormat = dateFormat == null ? "yyyy-MM-dd HH:mm:ss" : dateFormat;
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
return date != null ? sdf.format(date) : null;
}
/**
* 生成cron表达式 ss mm HH dd MM ? yyyy
* convert Date to cron ,eg. "0 06 10 15 1 ? 2014"
*
* @param date : 时间点
*/
public static String getCron(Date date) {
String dateFormat = "ss mm HH dd MM ? yyyy";
return formatDateByPattern(date, dateFormat);
}
/**
* 生成cron表达式 ss mm HH dd MM ?
* convert Date to cron ,eg. "0 06 10 15 1 ?"
*
* @param date : 时间点
* @param type : 类型 日/周/月
*/
public static String getLoopCron(Date date, String type, Integer week, Integer day) {
String dateFormat = "ss mm HH";
// dd MM ?
String cron = formatDateByPattern(date, dateFormat);
switch (type) {
case "Day":
return cron + " * * ?";
case "Week":
return cron + " ? * " + getCurrentWeek(week);
case "Month":
return cron + " " + day + " * ?";
default:
return "false";
}
}
/**
* 获取当前星期的字符 MON TUE WED THU FRI SAT SUN
*
* @param week : 周 1 2 3 4 5 6 7
* @return 星期字符
*/
public static String getCurrentWeek(Integer week) {
String[] weeks = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
return weeks[week - 1];
}
}
三、定时任务到时–执行文件
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
/**
* 定时任务开始--所执行位置
*/
@Component
public class SomThingTimeJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context){
//写自己要实现的业务逻辑
System.out.println("开始执行");
//拿到定时任务新建是传递的参数
System.out.println("传递得数据是:"+context.getJobDetail().getJobDataMap().get("userId"));
System.out.println("结束执行");
}
}
增删改查
一、新建定时任务
一(1)、新建定时任务接口
@Autowired
private QuartzService quartzService;
/**
* 开启一个定时任务
*
* @param jobClassName --SomThingTimeJob类的绝对路径 com.example.quartz.demos.utils.SomThingTimeJob
* @param jobName --定时任务唯一标识
* @param cronExpression -- cron表达式 "00 50 13 23 04 ? 2023":执行一次
* @param userId --可携带参数,在开始和执行进行传输
*/
@GetMapping("/addPost")
public int addPost(@RequestParam(value = "jobClassName") String jobClassName,
@RequestParam(value = "jobName") String jobName,
@RequestParam(value = "cronExpression") String cronExpression,
@RequestParam("userId") Integer userId) throws Exception {
return quartzService.addJob(ClassUtil.getClass(jobClassName), jobName, cronExpression, userId);
}
一(2)、新建定时任务实现
@Autowired
private Scheduler scheduler;
public int addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobTime, Integer userId) {
//定义返回结果
int i = 0;
try {
// 创建jobDetail实例,绑定Job实现类 --- 指明job的名称,所在组的名称,以及绑定job类 --- 以及可以携带的参数
// 任务名称和组构成任务key
JobDetail jobDetail = JobBuilder.newJob(jobClass) //绑定Job实现类
.withIdentity(jobName) // 指明job的名称(唯一)
.usingJobData("userId", userId) //携带的参数(到时执行文件所获取的文件)
.build();
// 定义调度触发规则
// 使用cornTrigger规则
// 触发器key
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName)
.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
.withSchedule(CronScheduleBuilder.cronSchedule(jobTime).inTimeZone(TimeZone.getTimeZone("Asia/Shanghai")))
.startNow()
.build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
i++;
}
} catch (Exception e) {
e.printStackTrace();
}
return i;
}
一(3)、新建定时任务调用(postMan)
参数说明:
- jobClassName:定时任务到时需执行的文件,绝对位置
- jobName:定时任务唯一标识
- cronExpression:cron表达式
- userId:携带参数(举例)
二、删除定时任务
接口类型以上,不重复,直接上实现层
/**
* 删除任务一个job
* jobNmae:
*/
public Boolean deleteJob(String jobName) {
Boolean res = null;
try {
res = scheduler.deleteJob(new JobKey(jobName)); //jobName某个定时任务唯一标识
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
接口调用
三、修改定时任务
接口类型以上,不重复,直接上实现层:
/**
* 修改 一个job的 时间表达式
* jobName 定时任务唯一标识
* jobTime 需要修改的cron表达式
*/
public Date updateJob(String jobName,String jobTime) {
//定义返回数据类型
Date resDate = null;
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder
.cronSchedule(jobTime) //修改该定时任务的 cron表达式
.inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))).build();
// 重启触发器
resDate = scheduler.rescheduleJob(triggerKey, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
return resDate;
}
参数说明:
- jobName:定时任务唯一标识
- jobTime 需要修改的cron表达式
四、获取所有计划中的任务列表
/**
* 获取所有计划中的任务列表
*/
public List<Map<String, Object>> queryAllJob() {
//定义返回类型
List<Map<String, Object>> jobList = null;
try {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
jobList = new ArrayList<Map<String, Object>>();
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
Map<String, Object> map = new HashMap<>();
map.put("jobName", jobKey.getName()); //定时任务唯一标识--名称
map.put("jobGroupName", jobKey.getGroup()); //定时任务分组情况
map.put("description", "触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
map.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
map.put("jobTime", cronExpression);
}
jobList.add(map);
}
}
} catch (SchedulerException e) {
e.printStackTrace();
}
return jobList;
}
直接接口调用
localhost:8080/user/queryAllJob
五、获取所有计划中的任务列表
/**
* 获取所有正在运行的job
*/
public List<Map<String, Object>> queryRunJob() {
List<Map<String, Object>> jobList = null;
try {
List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
for (JobExecutionContext executingJob : executingJobs) {
Map<String, Object> map = new HashMap<String, Object>();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
map.put("jobName", jobKey.getName());
map.put("jobGroupName", jobKey.getGroup());
map.put("description", "触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
map.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
map.put("jobTime", cronExpression);
}
jobList.add(map);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
return jobList;
}
六、暂停、恢复一个job、立即执行
/**
* 暂停一个job
*/
public void pauseJob(String jobName) {
try {
JobKey jobKey = JobKey.jobKey(jobName);
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 恢复一个job
*
*/
public void resumeJob(String jobName) {
try {
JobKey jobKey = JobKey.jobKey(jobName);
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 立即执行一个job
*/
public void runAJobNow(String jobName) {
try {
JobKey jobKey = JobKey.jobKey(jobName);
scheduler.triggerJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
总结
- 优点:没有存储表格和过多调用,比较便捷。。。
- 缺点:通过这种方式调用设置的定时任务在成功后,服务不能重启,一旦重启,定时任务清空。。。