项目中需要页面动态新增定时任务,还需要进行任务删除的功能。
借鉴了其他人的做法。现将设计方式记录如下:
1、springboot项目直接依赖
org.springframework.boot
spring-boot-starter-quartz
2、在启动类上加@EnableScheduling
3、添加quartz配置文件quartz.properties
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
4、配置类
@Configuration
@Slf4j
public class QuartzThreadPoolConfig {
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Bean
@Order(2)
public SchedulerFactoryBean getSchedulerFactoryBean() throws IOException {
if(threadPoolTaskExecutor == null){
log.error("threadPoolTaskExecutor is null");
System.exit(0);
}
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/config/quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
//创建SchedulerFactoryBean
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setTaskExecutor(threadPoolTaskExecutor);
factory.setQuartzProperties(propertiesFactoryBean.getObject());
//这样当spring关闭时,会等待所有已经启动的quartz job结束后spring才能完全shutdown。
factory.setWaitForJobsToCompleteOnShutdown(true);
factory.setOverwriteExistingJobs(false);
factory.setStartupDelay(1);
return factory;
}
@Bean("taskExecutor")
@Primary
@Order(1)
public ThreadPoolTaskExecutor getThreadPoolTaskExecutor(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setMaxPoolSize(5);
threadPoolTaskExecutor.setCorePoolSize(2);
RejectedExecutionHandler handler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.error("线程池超过最大容量,进行扩容 {} ",executor.getPoolSize());
executor.setMaximumPoolSize(10);
Thread thread = new Thread(r);
thread.start();
log.error(r.toString());
}
};
threadPoolTaskExecutor.setRejectedExecutionHandler(handler);
return threadPoolTaskExecutor;
}
}
5、监听器,项目启动从数据库加载需要进行执行的任务
@Component
public class QuartzInitLisenter implements ApplicationListener{
@Resource
private SchedulerAllJob schedulerAllJob;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
schedulerAllJob.scheduleJobs();
} catch (SchedulerException e) {
e.printStackTrace();
}
System.out.println("ssssss>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}
}
6、新增、删除任务
@Component
public class SchedulerAllJob {
@Resource
private SchedulerFactoryBean schedulerFactoryBean;
@Resource
private QuartzMapper quartzMapper;
/*
* 此处可以注入数据库操作,查询出所有的任务配置
*/
/**
* 该方法用来启动所有的定时任务
* @throws SchedulerException
*/
public void scheduleJobs() throws SchedulerException {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
scheduleJob1(scheduler);
}
public void stop() throws SchedulerException {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
scheduler.clear();
}
public void remove(int i) throws SchedulerException {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
boolean deleteJob = scheduler.deleteJob(new JobKey("job" + i, "group1"));
System.out.println(deleteJob);
}
public void add(int i) throws SchedulerException {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobDetail jobDetail = JobBuilder.newJob(ScheduledJob.class) .withIdentity("job" + i, "group1").build();
// 每5s执行一次
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("*/5 * * * * ?");
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job" + i, "group1") .withSchedule(scheduleBuilder).build();
cronTrigger.getJobDataMap().put("taskId",i);
scheduler.scheduleJob(jobDetail,cronTrigger);
}
/**
* 配置Job1
* 此处的任务可以配置可以放到properties或者是放到数据库中
* @param scheduler
* @throws SchedulerException
*/
private void scheduleJob1(Scheduler scheduler) throws SchedulerException{
Wrapper wrapper = new EntityWrapper<>();
List tasks = quartzMapper.selectList(wrapper);
if(tasks != null && !tasks.isEmpty()){
for (QuartzTask task : tasks) {
JobKey jobKey = new JobKey(task.getJobName(), task.getJobGroup());
JobDetail jobDetail = JobBuilder.newJob(ScheduledJob.class) .withIdentity(jobKey).build();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getQuartzTime());
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup()) .withSchedule(scheduleBuilder).build();
cronTrigger.getJobDataMap().put("taskId", task.getId());
if (!scheduler.checkExists(jobKey)) {
scheduler.scheduleJob(jobDetail,cronTrigger);
}
}
}
}
}
7、业务执行类
@Slf4j
public class ScheduledJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("schedule job1 is running {} {}",jobExecutionContext.getTrigger().getJobDataMap().get("taskId"),jobExecutionContext.getJobInstance().toString());
//根据taskId去数据库获取响应信息,进行执行
//todo 业务代码
}
}
8、简易的任务controller
@RestController
@RequestMapping("/quartz")
public class QuartzController {
@Autowired
public SchedulerAllJob myScheduler;
@RequestMapping("/start")
public String schedule() throws SchedulerException {
myScheduler.scheduleJobs();
return "success";
}
@RequestMapping("/stop")
public String stop() throws SchedulerException {
myScheduler.stop();
return "success";
}
@RequestMapping("/add/{id}")
public String add(@PathVariable("id") Integer id) throws SchedulerException {
myScheduler.add(id);
return "success";
}
@RequestMapping("/del/{id}")
public String del(@PathVariable("id") Integer id) throws SchedulerException {
myScheduler.remove(id);
return "success";
}
}
9、实体类及Mapper
@lombok.Data
public class QuartzTask {
private Long id;
private String type;
private String jobGroup;
private String jobName;
private String invokeParam;
private String quartzTime;
private String status;
private Date executeEndtime;
}
@Mapper
public interface QuartzMapper extends BaseMapper {
//采用mybatis-plus
}
以上就是功能的测试demo
参考资料:
1、https://blog.csdn.net/zhaoyahui_666/article/details/78835128
2、https://blog.csdn.net/fanghuainihao/article/details/95462526