Quartz定时任务-动态增删改
前言
ps:虽然说是动态实现,但是实际的任务逻辑还是需要手写Job类来实现,然后再去调度器中调度
入参中的*jobClass与jobDetailName
*都是你所创建的Job类所在地即:包路径 + 类名
其他参数都是动态可配,亦可修改的
创建Controller
ps:控制层个人习惯吧业务逻辑统一存放在业务层处理,控制层一般只存在简单的入参判断等. 具体的业务代码统一交给业务层使用
/**
* @author xiao-_-wu
* @date 2021/3/22 10:46
*/
@Slf4j
@RestController
@RequestMapping("/test/task")
public class TestTaskController {
@Resource
private TestTaskService testTaskService;
@GetMapping("/stop/{jobDetailName}")
public String stopTask(@PathVariable String jobDetailName){
log.info("Controller-----停止定时任务");
return testTaskService.stopTask(jobDetailName);
}
@GetMapping("/restore/{jobDetailName}")
public String restoreTask(@PathVariable String jobDetailName){
log.info("Controller-----恢复定时任务");
return testTaskService.restoreTask(jobDetailName);
}
@PostMapping("/add")
public String addTask(JobDetailsDTO dto){
log.info("Controller-----新增定时任务");
return testTaskService.addTask(dto);
}
@DeleteMapping("/remove/{jobDetailName}")
public String removeTask(@PathVariable String jobDetailName){
log.info("Controller-----删除定时任务");
return testTaskService.removeTask(jobDetailName);
}
@PutMapping("/modify")
public String modifyTask(JobDetailsDTO dto){
log.info("Controller-----修改定时任务");
return testTaskService.modifyTask(dto);
}
@GetMapping("/list")
public JobAndTriggerDTO listTask(){
log.info("Controller-----获取任务列表");
return testTaskService.listTask();
}
}
业务层接口
/**
* @author xiao-_-wu
*/
public interface TestTaskService {
/**
* 暂停定时任务
* @param jobDetailName 名称
* @return ret
*/
String stopTask(String jobDetailName);
/**
* 恢复定时任务
* @param jobDetailName 名称
* @return ret
*/
String restoreTask(String jobDetailName);
/**
* 新增定时任务
* @return ret
* @param dto
*/
String addTask(JobDetailsDTO dto);
/**
* 删除定时任务
* @return ret
* @param jobClassName
*/
String removeTask(String jobClassName);
/**
* 修改定时任务
* @return ret
* @param dto
*/
String modifyTask(JobDetailsDTO dto);
/**
* 查看当前任务信息
* @return ret
*/
JobAndTriggerDTO listTask();
}
业务实现类
/**
* @author xiao-_-wu
* @date 2021/3/22 11:34
*/
@Slf4j
@Service
public class TestTaskServiceImpl implements TestTaskService {
@Resource
private Scheduler scheduler;
@Override
public String stopTask(String jobDetailName) {
JobKey jobKey = JobKey.jobKey(jobDetailName);
try {
if (!isJobDetail(jobKey)){
return "定时任务不存在或已删除";
}
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
return "暂停成功";
}
@Override
public String restoreTask(String jobDetailName) {
JobKey jobKey = JobKey.jobKey(jobDetailName);
try {
if (!isJobDetail(jobKey)){
return "定时任务不存在或已删除";
}
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
return "恢复成功";
}
@Override
public String addTask(JobDetailsDTO dto) {
try {
// 启动调度器
scheduler.start();
// 获取创建的job任务
Job job = JobUtil.getJobClass(dto.getJobClass());
// 创建JobDetail
JobDetail jobDetail = JobBuilder
.newJob(job.getClass())
// 给Job任务取名,分组
.withIdentity(dto.getJobClass(), dto.getJobGroup())
.build();
jobDetail.requestsRecovery();
jobDetail.getJobDataMap().put("jobKey", dto.getMassage());
// 创建Trigger
Trigger trigger = TriggerBuilder
.newTrigger()
// 给触发器设置名称和分组
.withIdentity(dto.getJobClass(), dto.getTriggerGroup())
// 设置定时策略 这里使用createSimple()方式, 也可以使用cron定时策略 createCron()
.withSchedule(createSimple(dto.getTime()))
.build();
scheduler.scheduleJob(jobDetail, trigger);
System.out.println("-----定时任务启动-----");
/* 创建调度器,进行任务调度, 这里调度器交给了Spring容器进行管理 所以没有用这里的方法
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
// 这是暂停定时任务的方法
// scheduler.shutdown();
*/
} catch (IllegalAccessException e) {
System.out.println(e.getMessage());
return "异常: 非法访问异常";
} catch (InstantiationException e) {
System.out.println(e.getMessage());
return "异常: 实例化异常";
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
return "异常: 类找不到异常";
} catch (SchedulerException e) {
e.printStackTrace();
}
return "定时任务创建成功";
}
@Override
public String removeTask(String jobClassName) {
schedulerDelete(jobClassName);
return "删除成功";
}
@Override
public String modifyTask(JobDetailsDTO dto) {
// 先删除任务
schedulerDelete(dto.getJobClass());
// 创建定时任务
addTask(dto);
return "修改成功";
}
@Override
public JobAndTriggerDTO listTask() {
List<Trigger> triggers = new ArrayList<>();
List<JobDetail> jobDetails = new ArrayList<>();
try {
// 获取trigger集合
listTrigger(triggers);
// 获取JobDetail集合
listJobDetail(jobDetails);
} catch (Exception e) {
log.error("获取定时任务信息出错", e);
throw new RuntimeException("获取定时任务信息异常");
}
JobAndTriggerDTO dto = new JobAndTriggerDTO();
List<JobInfoDTO> jobInfos = new ArrayList<>();
for (JobDetail jobDetail : jobDetails) {
// 存入jobKey信息
KeyDTO keyDTO = KeyDTO.builder()
.key(jobDetail.getKey().getName())
.group(jobDetail.getKey().getGroup())
.build();
// 存入JobDetail信息
jobInfos.add(JobInfoDTO.builder()
.jobDataMap(jobDetail.getJobDataMap())
.jobKey(keyDTO)
.className(jobDetail.getJobClass().getName())
.build());
}
// 存入返回值
dto.setJobInfos(jobInfos);
return dto;
}
/**
* 简单模式的Trigger
* @return ret
* @param time 间隔时间/秒
*/
private SimpleScheduleBuilder createSimple(Integer time){
return SimpleScheduleBuilder
// 定时策略类型 普通
.simpleSchedule()
// 给定间隔时间 单位/秒
.withIntervalInSeconds(time)
.repeatForever();
}
/**
* Cron 模式下的Trigger
* ps:这里也可以使用Cron模式,使用这种模式需要了解 cron 语法
* @return ret
*/
private CronScheduleBuilder createCron(){
return CronScheduleBuilder
.cronSchedule("0 0/5 * * *?");
}
/**
* 判断当前Job是否存在
* @param jobKey jobKey
* @return ret
* @throws SchedulerException
*/
private boolean isJobDetail(JobKey jobKey) throws SchedulerException {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
return jobDetail != null;
}
/**
* 删除定时任务
*
* @param jobClassName job名称
*/
private void schedulerDelete(String jobClassName) {
try {
// 暂停Trigger
scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
// 从调度器中删除置顶Trigger
scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
// 删除Job任务
scheduler.deleteJob(JobKey.jobKey(jobClassName));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException("删除定时任务失败");
}
}
/**
* 获取触发器列表
* @param triggers 触发器
* @return ret
* @throws SchedulerException 调度器程序异常
*/
private List<Trigger> listTrigger(List<Trigger> triggers) throws SchedulerException {
// 获取Scheduler下的所有group
List<String> triggerGroupNames = scheduler.getTriggerGroupNames();
// 获取所有Trigger名称
for (String str : triggerGroupNames) {
GroupMatcher<TriggerKey> groupMatcher = GroupMatcher.triggerGroupEquals(str);
Set<TriggerKey> set = scheduler.getTriggerKeys(groupMatcher);
for (TriggerKey key : set){
triggers.add(scheduler.getTrigger(key));
}
}
return triggers;
}
/**
* 获取定时任务列表
* @param jobDetails job详情
* @return ret
* @throws SchedulerException 调度器程序异常
*/
private List<JobDetail> listJobDetail(List<JobDetail> jobDetails) throws SchedulerException {
List<String> jobGroupNames = scheduler.getJobGroupNames();
for (String str : jobGroupNames) {
GroupMatcher<JobKey> groupMatcher = GroupMatcher.jobGroupEquals(str);
Set<JobKey> set = scheduler.getJobKeys(groupMatcher);
for (JobKey key : set){
jobDetails.add(scheduler.getJobDetail(key));
}
}
return jobDetails;
}
}
其他类(entity、dto等)
列表参数类
/**
* 列表参数类
* @author xiao-_-wu
* @date 2021/3/25 16:55
*/
@Data
public class JobAndTriggerDTO implements Serializable {
private static final long serialVersionUID = -686788394437570442L;
/**
* jobDetail集合
*/
List<JobInfoDTO> jobInfos;
}
通用key类
/**
* 用来获取key 和 group
* @author xiao-_-wu
* @date 2021/3/26 10:38
*/
@Data
@Builder
public class KeyDTO {
/**
* key值
*/
private String key;
/**
* 分组
*/
private String group;
}
job任务信息类
/**
* job信息类
* @author xiao-_-wu
* @date 2021/3/26 10:39
*/
@Data
@Builder
public class JobInfoDTO {
/**
* job
*/
private KeyDTO jobKey;
/**
* 包路径
*/
private String className;
/**
* map(用于传值)
*/
private JobDataMap jobDataMap;
}
创建定时任务入参类
/**
* job入参
*
* @author xiao-_-wu
* @date 2021/3/25 10:10
*/
@Data
public class JobDetailsDTO {
/**
* job类包名
*/
private String jobClass;
/**
* job定时工作类型,非必传
*/
private Integer jobType;
/**
* 工作分组,非必传
*/
private String jobGroup;
/**
* 触发器分组,非必传
*/
private String triggerGroup;
/**
* 其他信息,非必传
*/
private String massage;
/**
* 间隔时间/ 秒
*/
private Integer time;
}
工具类
/**
* job工具类
* @author xiao-_-wu
* @date 2021/3/25 10:20
*/
public class JobUtil {
/**
* 根据类包名获取类
* @param jobClass 包名
* @return ret'
* @throws IllegalAccessException 非法访问异常
* @throws InstantiationException 实例化异常
* @throws ClassNotFoundException 类找不到异常
*/
public static Job getJobClass(String jobClass) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Class<?> job = Class.forName(jobClass);
return (Job)job.newInstance();
}
}
博客地址:Quartz定时任务(二)-CSDN博客