Spring Boot 整合 Quartz 實現 Java 定時任務的動態(tài)配置
閱讀本文大概需要 6 分鐘。
作者:小賣鋪的老爺爺
鏈接:cnblogs.com/laoyeye/p/9352002.html


maven依賴
<dependency>
????<groupId>org.quartz-schedulergroupId>
????<artifactId>quartzartifactId>
????<version>2.2.1version>
dependency>
<dependency>
????<groupId>org.springframeworkgroupId>
????<artifactId>spring-context-supportartifactId>
dependency>
CREATE?TABLE?`sys_task`?(
??`id`?bigint(20)?NOT?NULL?AUTO_INCREMENT,
??`job_name`?varchar(255)?DEFAULT?NULL?COMMENT?'任務名',
??`description`?varchar(255)?DEFAULT?NULL?COMMENT?'任務描述',
??`cron_expression`?varchar(255)?DEFAULT?NULL?COMMENT?'cron表達式',
??`bean_class`?varchar(255)?DEFAULT?NULL?COMMENT?'任務執(zhí)行時調用哪個類的方法 包名+類名',
??`job_status`?varchar(255)?DEFAULT?NULL?COMMENT?'任務狀態(tài)',
??`job_group`?varchar(255)?DEFAULT?NULL?COMMENT?'任務分組',
??`create_user`?varchar(64)?DEFAULT?NULL?COMMENT?'創(chuàng)建者',
??`create_time`?datetime?DEFAULT?NULL?COMMENT?'創(chuàng)建時間',
??`update_user`?varchar(64)?DEFAULT?NULL?COMMENT?'更新者',
??`update_time`?datetime?DEFAULT?NULL?COMMENT?'更新時間',
??PRIMARY?KEY?(`id`)
)?ENGINE=MyISAM AUTO_INCREMENT=32?DEFAULT?CHARSET=utf8;
代碼邏輯
@Configuration
public?class?QuartzConfigration?{
????@Autowired
????private?JobFactory jobFactory;
????@Bean
????public?SchedulerFactoryBean?schedulerFactoryBean()?{
????????SchedulerFactoryBean schedulerFactoryBean =?new?SchedulerFactoryBean();
????????try?{
????????????schedulerFactoryBean.setOverwriteExistingJobs(true);
????????????schedulerFactoryBean.setQuartzProperties(quartzProperties());
????????????schedulerFactoryBean.setJobFactory(jobFactory);
????????}?catch?(Exception e) {
????????????e.printStackTrace();
????????}
????????return?schedulerFactoryBean;
????}
????// 指定quartz.properties,可在配置文件中配置相關屬性
????@Bean
????public?Properties?quartzProperties()?throws?IOException?{
????????PropertiesFactoryBean propertiesFactoryBean =?new?PropertiesFactoryBean();
????????propertiesFactoryBean.setLocation(new?ClassPathResource("/config/quartz.properties"));
????????propertiesFactoryBean.afterPropertiesSet();
????????return?propertiesFactoryBean.getObject();
????}
????// 創(chuàng)建schedule
????@Bean(name =?"scheduler")
????public?Scheduler?scheduler()?{
????????return?schedulerFactoryBean().getScheduler();
????}
}
@Component
@Order(value =?1)
public class ScheduleJobInitListener implements CommandLineRunner {
????@Autowired
????TaskService scheduleJobService;
????@Override
????public void run(String... arg0) throws Exception {
????????try?{
????????????scheduleJobService.initSchedule();
????????}?catch?(Exception e) {
????????????e.printStackTrace();
????????}
????}
}
Interface used to indicate that a bean should run when it is contained within a SpringApplication. Multiple CommandLineRunner beans can be defined within the same application context and can be ordered using the Ordered interface or Order @Order annotation.
接口被用作將其加入spring容器中時執(zhí)行其run方法。多個CommandLineRunner可以被同時執(zhí)行在同一個spring上下文中并且執(zhí)行順序是以order注解的參數順序一致。
@Override
????public?void?initSchedule()?throws?SchedulerException?{
????????// 這里獲取任務信息數據
????????ListjobList = taskMapper.list();
????????for?(TaskDO task : jobList) {
????????????if?(JobStatusEnum.RUNNING.getCode().equals(task.getJobStatus())) {
????????????????quartzManager.addJob(task);
????????????}
????????}
????}
/**
?????* 添加任務*/
????@SuppressWarnings("unchecked")
????public?void?addJob(TaskDO task) {
????????try?{
????????????// 創(chuàng)建jobDetail實例,綁定Job實現類
????????????// 指明job的名稱,所在組的名稱,以及綁定job類
????????????Class?extends?Job> jobClass = (Class?extends?Job>) (Class.forName(task.getBeanClass()).newInstance()
????????????????????.getClass());
????????????JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getJobGroup())// 任務名稱和組構成任務key
????????????????????.build();
????????????// 定義調度觸發(fā)規(guī)則
????????????// 使用cornTrigger規(guī)則
????????????Trigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup())// 觸發(fā)器key
????????????????????.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
????????????????????.withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).startNow().build();
????????????// 把作業(yè)和觸發(fā)器注冊到任務調度中
????????????scheduler.scheduleJob(jobDetail, trigger);
????????????// 啟動
????????????if?(!scheduler.isShutdown()) {
????????????????scheduler.start();
????????????}
????????}?catch?(Exception e) {
????????????e.printStackTrace();
????????}
????}
@Component
public?class?JobFactory?extends?AdaptableJobFactory?{
????//這個對象Spring會幫我們自動注入進來,也屬于Spring技術范疇.
????//為什么需要這個類呢,在我寫的這個demo中,大家可以將此類刪掉,發(fā)現程序也可以正確運行,可是我為什么還是加上呢。
????//大家可以看下我們的任務類,大家可以看到Job對象的實例化過程是在Quartz中進行的,這時候我們將spring的東西注入進來,肯定是行不通的,所以需要這個類
????@Autowired
????private?AutowireCapableBeanFactory capableBeanFactory;
????@Override
????protected?Object?createJobInstance(TriggerFiredBundle bundle)?throws?Exception?{
????????//調用父類的方法
????????Object jobInstance =?super.createJobInstance(bundle);
????????//進行注入
????????capableBeanFactory.autowireBean(jobInstance);
????????return?jobInstance;
????}
}
@DisallowConcurrentExecution?//作業(yè)不并發(fā)
@Component
public class HelloWorldJob implements Job{
????@Override
????public void execute(JobExecutionContext arg0) throws JobExecutionException {
????????
????????System.out.println("歡迎使用yyblog,這是一個定時任務 --小賣鋪的老爺爺!"+ DateUtils.fullTime(new Date()));
????????
????}
}
public?void?pauseJob(TaskDO task)?throws?SchedulerException?{
????????JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
????????scheduler.pauseJob(jobKey);
????}
public?void?resumeJob(TaskDO task)?throws?SchedulerException?{
????????JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
????????scheduler.resumeJob(jobKey);
????}
public?void?deleteJob(TaskDO task)?throws?SchedulerException?{
????????JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
????????scheduler.deleteJob(jobKey);
????}
public?void?runJobNow(TaskDO task)?throws?SchedulerException?{
????????JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
????????scheduler.triggerJob(jobKey);
????}
public?void?updateJobCron(TaskDO task)?throws?SchedulerException?{
????????TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
????????CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
????????CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
????????trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
????????scheduler.rescheduleJob(triggerKey, trigger);
????}
推薦閱讀:
今天終于搞懂了:為什么 Java 的 main 方法必須是 public static void?
微信掃描二維碼,關注我的公眾號
朕已閱?
評論
圖片
表情

