终于抽出时间来写这篇博客了,前段时间用到了调度任务,并且由于要求动态控制,于是就研究了一下,也是遇到了挺多坑,今天来分享一下整合Quartz。
关于Quartz 我在这就不多介绍了,如果有兴趣可以去百度搜索一下。
以往整合Quartz时需要在数据库里面配置对应的表,但是今天我们不那么配置,只需要一张表即可。直奔主题。
create table base_quartz_config
(
configid varchar(64) not null
primary key,
quarta_name varchar(100) null comment '任务名称',
quarta_group varchar(100) null comment '任务组',
status int null comment '状态',
quartz_class varchar(200) null comment '类全名',
remark varchar(200) null comment '备注',
createuserid varchar(64) null comment '创建人',
expression varchar(64) null comment '表达式',
createtime datetime null
)
collate = utf8_bin;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
MySchedulerFactory.java:
@Service("MySchedulerFactory")
@Component
public class MySchedulerFactory {
private static Logger logger = LoggerFactory.getLogger(MySchedulerFactory.class);
@Autowired
SchedulerFactoryBean schedulerFactoryBean;
@Autowired
private BaseQuartzService baseQuartzService;
/**
* 任务配置读取服务
*/
@Autowired
private BaseQuartzService baseQuartzConfigService;
public void scheduleJobs() throws SchedulerException {
Scheduler scheduler = getScheduler();
// 为了避免org.quartz.ObjectAlreadyExistsException,在执行前将scheduler进行清理
scheduler.clear();
startJob(scheduler);
}
/**
* 获取scheduler
*
* @return
* @author Java最强的男人
*/
private Scheduler getScheduler() {
return schedulerFactoryBean.getScheduler();
}
/**
* 项目启动 开启任务
*
* @param scheduler
* @author Java最强的男人
*/
private void startJob(Scheduler scheduler) {
try {
List<BaseQuartzConfig> jobList = baseQuartzConfigService.findAll();
for (BaseQuartzConfig config : jobList) {
try {
// 1-暂停的任务 0-正常运行任务
if (1L == config.getStatus()) {
continue;
}
String classz = config.getQuartzClass();
if (!StringUtils.isEmpty(classz)) {
@SuppressWarnings("unchecked")
Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(classz);
JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(config.getConfigid(), config.getQuartaGroup())
.build();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(config.getExpression());
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(config.getConfigid(), config.getQuartaGroup())
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
}
} catch (Exception e) {
logger.info("定时启动异常:" + config.getQuartaName() + " 异常信息:" + e.getMessage());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 任务暂停
*
* @param id
* @throws Exception
* @author Java最强的男人
*/
public void pauseJob(String id) throws Exception {
Scheduler scheduler = getScheduler();
BaseQuartzConfig QuartzConfig = baseQuartzConfigService.get(String.valueOf(id));
JobKey jobKey = JobKey.jobKey(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup());
scheduler.deleteJob(jobKey);
baseQuartzService.update(id,1);
}
/**
* 任务恢复
*
* @param id
* @throws Exception
* @author Java最强的男人
*/
public void resumeJob(String id) throws Exception {
Scheduler scheduler = getScheduler();
BaseQuartzConfig QuartzConfig = baseQuartzConfigService.get(String.valueOf(id));
JobKey jobKey = JobKey.jobKey(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup());
Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(QuartzConfig.getQuartzClass());
JobDetail jobDetail1 = scheduler.getJobDetail(jobKey);
if (jobDetail1 == null) {
JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup())
.build();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(QuartzConfig.getExpression());
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup())
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
baseQuartzService.update(id,0);
} else {
scheduler.resumeJob(jobKey);
}
}
}
MyJobFactory.java:
@Component
public class MyJobFactory extends AdaptableJobFactory {
private final AutowireCapableBeanFactory capableBeanFactory;
public MyJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
this.capableBeanFactory = capableBeanFactory;
}
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
创建定时任务监听类:
StartSchedulerListener.java:
@Configuration
public class StartSchedulerListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
public MySchedulerFactory mySchedulerFactory;
private final MyJobFactory myJobFactory;
public StartSchedulerListener(MyJobFactory myJobFactory) {
this.myJobFactory = myJobFactory;
}
// springboot 启动监听
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
mySchedulerFactory.scheduleJobs();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
//注入SchedulerFactoryBean
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setStartupDelay(5);//延时5秒启动
schedulerFactoryBean.setJobFactory(myJobFactory);
return schedulerFactoryBean;
}
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
@Configuration
@Component
@EnableScheduling
public class ScheduleTask1 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
System.out.print("任务执行1 :");
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
既然是动态配置,那么还需要编写接口类:
@RestController
@CrossOrigin
@RequestMapping("quartz")
@Api(value = "调度任务管理", tags = "调度任务管理")
public class QuartzController {
@Autowired
private MySchedulerFactory schedulerFactory;
@ApiOperation(value = "任务暂停", notes = "任务暂停")
@PostMapping("pauseJob/{configId}")
public R pauseJob(@PathVariable String configId) {
try {
schedulerFactory.pauseJob(configId);
return R.ok();
} catch (Exception e) {
e.printStackTrace();
return R.error();
}
}
@ApiOperation(value = "任务恢复", notes = "任务恢复")
@PostMapping("resumeJob/{configId}")
public R resumeJob(@PathVariable String configId) {
try {
schedulerFactory.resumeJob(configId);
return R.ok();
} catch (Exception e) {
e.printStackTrace();
return R.error();
}
}
}
以上代码就实现了对于调度任务的动态管理。